News:

Let's find out together what makes a PIC Tick!

Main Menu

SSD1311 Oled driver code conversion - SOLVED

Started by SCV, Mar 28, 2023, 03:06 PM

Previous topic - Next topic

SCV

Trying to bring an Oled display from Midas to life to replace a standard character LCD module. Display is a MCOB21605GX-EBP which uses SSD1311 controller and is pin compatible and running on a 46K22 at 5volt. Midas have given me an example script, but it's for 8bit mode.

Could anyone with experience of C help me translate into PB please...

//Sample Code:
//8-bit 6800 interface mode
//=============================================================
//    Midas Dislpays
//    OLED Module        
//    Contraller :SSD1311
//    Author     :
//    history     :
//==============================================================
#include    <reg51.h>
#include     <stdio.h>          // define I/O functions
#include     <INTRINS.H>      // KEIL FUNCTION     

#define    Data_BUS    P1

sbit        busy    =P1^7;
sbit        RS    =P3^0;
sbit         RW    =P3^7;
sbit        E    =P3^4;

sbit        STP     =P2^0;
sbit        S_S    =P2^1;

char bdata  flag;
sbit busy_f  = flag^0;

void delay(unsigned char);
void CGRAM(void);
/*void CheckBusy(void);
void CGRAM(void);
void WriteIns(unsigned char);
void WriteData(unsigned char dat);
void WriteSerialData(unsigned char,unsigned char *);
void Initial_SSD1311(void);
void delay(unsigned char);
void FULL_ON(void);
void SHOW_CHAR(void);
void SHOW_CHARABCD(void);
void SQUARE(void) ;
void CROSS_DOT(void);
void CROSS_DOT2(void);
void SHOW_FONT(void) ;
void SHOW_WB(unsigned char m);
void ENT_SLEEP(void) ;
void EXIT_SLEEP(void);       
void STP_SC(void);       */
                         






/*=============================================================================
               DISPLAY DATA
===============================================================================*/
unsigned char code Page1[20]  ={"  ECO DISPLAY       "};   
unsigned char code Page2[20]  ={"  16 X 02 OLED      "};

// CGRAM has up to 8 characters of 5 x 8 dots, selectable by OPR0 and OPR1 pins
unsigned char code CGRAM1[40] ={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, //¦      00H
              0x1F,0x11,0x11,0x11,0x11,0x11,0x11,0x1F, //?          01H
            0x0A,0x15,0x0A,0x15,0x0A,0x15,0x0A,0x15, //?         02H
                  0x15,0x0A,0x15,0x0A,0x15,0x0A,0x15,0x0A,}; //?      03H

void CheckBusy(void)
{
    Data_BUS = 0xff;    //SET PORT1=INPUT
    RS = 0;                //SET IR  MODE RS=0
    RW = 1;              //SET READ MODE R/W=1
    do
    {
        E = 1;            //ENABLE LCM
        busy_f = busy;     //CHECK BUSY FLAGE(BIT7)
        E = 0;     }while(busy_f);
}
//=================================
void WriteIns(unsigned char ins)
{
      CheckBusy();
     RS = 0;
     RW = 0;
     Data_BUS = ins;
     E = 1;        //1us
     _nop_();    //1us
     E = 0;        //1us

}
//=================================
void WriteData(unsigned char dat)
{
    CheckBusy();
    RS = 1;   
    RW = 0;
    Data_BUS = dat;
    E = 1;
    _nop_();
    E = 0;

 
}





//=================================
void WriteSerialData(unsigned char count,unsigned char * MSG)
{
    unsigned char  i; 
    CheckBusy();
     RS = 1 ;
    RW = 0 ;
    for(i = 0; i<count;i++)
    {
        WriteData(MSG[i]);
    }
}

//=================================
void Initial_SSD1311(void)
{   
      WriteIns(0x2A);    //Enable Internal Regulator
    WriteIns(0x08);
    WriteIns(0x71);
    WriteData(0x5C);
    WriteIns(0x28);

    WriteIns(0x08);//Set Display Off

    WriteIns(0x2A);
    WriteIns(0x79);    //Set Display Clock Divide Ratio/Oscillator Frequency        
    WriteIns(0XD5);    // 
    WriteIns(0x70);    //       
    WriteIns(0X78);    //

    WriteIns(0x08);    //Set Display Mode

    WriteIns(0X06);    // Set Re-map

    WriteIns(0x72);//CGROM CDRAM Management
    WriteData(0x09);//01:ROMA 05:ROMB 09:ROMC

    WriteIns(0x79);//Set OLED Characterization

    WriteIns(0xDA);    //Set SEG Pins Hardware Configuration
    WriteIns(0X10);    //

    WriteIns(0xDC);    //Set Segment Low Voltage & Vcc On 
    WriteIns(0x03);

    delay(1);
 
    WriteIns(0X81);    //Set Contrast Control
    WriteIns(0xFF);    //Contrast increases as the value increases.   
      
    WriteIns(0XD9);    //Set Pre-Charge Period                              
    WriteIns(0xF1);   

    WriteIns(0XDB);    //Set VCOMH Deselect Level   
    WriteIns(0x40);  
 
    WriteIns(0x78);    //Exiting Set OLED Characterization
    WriteIns(0x28);

     WriteIns(0x08);//Set CGRAM
    CGRAM();
    WriteIns(0x01);// Clear Display
      
    WriteIns(0x80);    //Set display data RAM addr=00H    (SET ADDRESS    80H)    
 
    WriteIns(0x0C);    // Display ON   = 00001DCB (DISPLAY SET    0 1 D C B    0CH);Display ON,Cursor&Blink OFF          
}
//============================================

void delay(unsigned char m)      //100mS       
{
    unsigned char i,j,k;
     for(j = 0;j<m;j++)
     {
         for(k = 0; k<100;k++)      //250
         {
            for(i = 0; i<200;i++)
            {
            }
        }
     }   
}
//========SET CG_RAM DATA==========================
void CGRAM(void)
{
    WriteIns(0x40);   
    WriteSerialData(40,CGRAM1);
   
}

//=================================================
void FULL_ON(void)
{
   unsigned char i;

   WriteIns(0x80);    //Set display data RAM addr=00H    (SET ADDRESS    80H)
   for(i=20;i>0;i--)
   {
      WriteData(0x00);  }

    WriteIns(0xC0);    //Set display data RAM addr=40H
    for(i=20;i>0;i--)
   {
      WriteData(0x00);  }   
}

//=================================================
void SHOW_CHAR(void){
    unsigned char i;

    WriteIns(0x80);    //Set display data RAM addr=00H    (SET ADDRESS    80H)               
    WriteSerialData(20,Page1);

    WriteIns(0xC0);    //Set display data RAM addr=40H
    WriteSerialData(20,Page2);         
}                 

//===================================================
//                       SHOW_CHARABCD
//===================================================
void SHOW_CHARABCD(void)
 {
     unsigned char i,j;

    WriteIns(0x80);     //Set display data RAM addr=00H         
    j=0x41;
    for(i=20;i>0;i--)
    {
      WriteData(j);
      j++;
    }

    WriteIns(0xC0);    //Set display data RAM addr=40H
     j=0x41;
    for(i=20;i>0;i--)
    {
      WriteData(j);
      j++;
    } 
 }

//=======================================
//               SQUARE
//=======================================
 void SQUARE(void)
{
    unsigned char i;

    WriteIns(0x80);     //Set display data RAM addr=00H         

    for(i=20;i>0;i--)
    {
      WriteData(0x01);   
    }

    WriteIns(0xC0);    //Set display data RAM addr=40H
    for(i=20;i>0;i--)
    {
      WriteData(0x01);
    }

}
//=======================================
//               CROSS DOT
//=======================================
 void CROSS_DOT(void)
{
    unsigned char i;

    WriteIns(0x80);     //Set display data RAM addr=00H         

    for(i=20;i>0;i--)
    {
      WriteData(0x02);   
    }

    WriteIns(0xC0);    //Set display data RAM addr=40H
    for(i=20;i>0;i--)
    {
      WriteData(0x02);
    }

}
//=======================================
//               CROSS DOT2
//=======================================
 void CROSS_DOT2(void)
{
    unsigned char i;

    WriteIns(0x80);     //Set display data RAM addr=00H         

    for(i=20;i>0;i--)
    {
      WriteData(0x03);   
    }

    WriteIns(0xC0);    //Set display data RAM addr=40H
    for(i=20;i>0;i--)
    {
      WriteData(0x03);
    }



//=======================================
//               SHOW_FONT
//=======================================
 void SHOW_FONT(void)
{
    unsigned char i;

    WriteIns(0x80);     //Set display data RAM addr=00H         

    for(i=20;i>0;i--)
    {
      WriteData(0xA7);   
    }

    WriteIns(0xC0);    //Set display data RAM addr=40H
    for(i=20;i>0;i--)
    {
      WriteData(0xA7);
    }

//===========SHOW BLACK AND WHITE==========//
void SHOW_WB(unsigned char m)
{
   unsigned char i,j;   
   WriteIns(0x80);
   for(i=5;i>0;i--)
   {     
     for(j=1;j<=4;j++ )
     {
       
       if(j==m)  WriteData(0x00); else WriteData(0x20); }
    }
       WriteIns(0xC0);
    if(m==2) m=4; else m=(m+2)%4 ;
    for(i=5;i>0;i--)
   {          
     for(j=1;j<=4;j++ )
     {
    
      if(j==m)  WriteData(0x00); else WriteData(0x20); }
      
   }  
}
//=======Entering Sleep Mode=============
void ENT_SLEEP(void)  
{
    WriteIns(0x2A);    /*    RE : 1  ; IS : 0  ; SD : 0 */
    WriteIns(0x79);    /*    RE : 1  ; IS : 0  ; SD : 1 */    
    WriteIns(0xDC);    //Set VSL & GPIO (Vcc)
    WriteIns(0x02);    // Vcc OFF

    WriteIns(0x78);    /*    RE : 1  ; IS : 0  ; SD : 0 */
    WriteIns(0x28);    //
    WriteIns(0x08);    //Set Regulator

    WriteIns(0x2A);    /*    RE : 1  ; IS : 0  ; SD : 0 */
         WriteIns(0x71);    //
    WriteData(0x00);//
         WriteIns(0x28);    //

}

//=======Exiting Sleep Mode=============
void EXIT_SLEEP(void)
{
     WriteIns(0x2A);    /*    RE : 1  ; IS : 0  ; SD : 0 */
     WriteIns(0x79);    //*    RE : 1  ; IS : 0  ; SD : 1 */
    
     WriteIns(0x71);    //Set Regulator

     WriteData(0x5C);    //Enable internal Vdd regulator at 5V I/O application mode

     WriteIns(0xDC);    //Set VSL & GPIO (Vcc)On
     WriteIns(0x03);    //

     WriteIns(0x78);    /*    RE : 1  ; IS : 0  ; SD : 0 */
     WriteIns(0x28);    /*    RE : 0  ; IS : 0  ; SD : 0 */    
     WriteIns(0x0C);    //Display ON
}

void STP_SC(void)
{
    while(S_S)
    {
     if(STP==1)
     {
         delay(1);
         break; }
    }
}
void main(void)
{
    delay(10);//100mS
    Initial_SSD1311();
    FULL_ON();
    delay(10);
    STP_SC();
    SHOW_CHAR();
    delay(10);
    STP_SC();
    while(1)
    {   
        SHOW_CHARABCD();
        delay(10);
        STP_SC(); 
        SQUARE();
        delay(10);
        STP_SC();
        CROSS_DOT();
        delay(10);
        STP_SC();
        CROSS_DOT2();



        delay(10);
        STP_SC();    
    }   
}


What I have so far is from label SETUP:
DEVICE = 18F46K22
DECLARE XTAL = 16

SYMBOL ROW1    = $80
SYMBOL ROW2    = $C0

DIM LCD_LINE1 [16]  AS BYTE
DIM LCD_LINE2 [16]  AS BYTE
DIM TEMP_LCD        AS BYTE
DIM TEMP1           AS BYTE

SYMBOL LCD_RS   = LATB.2
SYMBOL LCD_E    = LATB.3
SYMBOL LCD_D4   = LATB.4
SYMBOL LCD_D5   = LATB.5
SYMBOL LCD_D6   = LATB.6
SYMBOL LCD_D7   = LATB.7
SYMBOL LED      = LATE.2

'=================================================
INIT:           ANSELA = %00100111                    'SET PORTA TO ANALOGUE
                ANSELB = 0
                ANSELC = 0
                ANSELD = 0
                ANSELE = 0

                LATA = 0
                LATB = 0
                LATC = $60
                LATD = 0
                LATE = 0

                'Ins & Outs
                TRISA = %111111                        'PortA ins & outs
                TRISB = %00000011                        'PortB ins & outs
                TRISC = %11111111                        'PortC ins & outs
                TRISD = %01111100                        'PortD ins & outs
                TRISE = %00000011                        'PortE ins & outs

                GOTO SETUP

'=================================================
LOAD_LCD:       TEMP_LCD = ROW1
                GOSUB LCD_CMD_OUT
                FOR TEMP1 = 0 TO 15
                    TEMP_LCD = LCD_LINE1 [TEMP1]
                    GOSUB LCD_TEXT_OUT
                NEXT
                TEMP_LCD = ROW2
                GOSUB LCD_CMD_OUT
                FOR TEMP1 = 0 TO 15
                    TEMP_LCD = LCD_LINE2 [TEMP1]
                    GOSUB LCD_TEXT_OUT
                NEXT

                RETURN

'=================================================
LCD_CMD_OUT:    LCD_RS = 0
                GOTO LCD_COMM

LCD_TEXT_OUT:   LCD_RS = 1

LCD_COMM:       DELAYUS 1
                LCD_D4 = TEMP_LCD.4
                LCD_D5 = TEMP_LCD.5
                LCD_D6 = TEMP_LCD.6
                LCD_D7 = TEMP_LCD.7
                DELAYUS 1
                LCD_E = 1
                DELAYUS 50
                LCD_E = 0
                DELAYUS 50
                LCD_D4 = TEMP_LCD.0
                LCD_D5 = TEMP_LCD.1
                LCD_D6 = TEMP_LCD.2
                LCD_D7 = TEMP_LCD.3
                DELAYUS 1
                LCD_E = 1
                DELAYUS 50
                LCD_E = 0
                DELAYUS 50
                LCD_RS = 0

                RETURN

'=================================================
MAIN:           DELAYMS 1000
                TOGGLE LED

                IF LED = 0 THEN
                    LCD_LINE1 = "  Hello World   "
                    LCD_LINE2 = "  Please work   "
                ELSE
                    LCD_LINE1 = "  Sorry...      "
                    LCD_LINE2 = "  Not today     "
                ENDIF
                GOSUB LOAD_LCD

                GOTO MAIN

'=================================================
SETUP:          DELAYMS 500         'Wait for LCD to stabilise

                LATB = $38          'Send a single 3 on bus for 4bit mode
                DELAYUS 50
                LATB = $30
                DELAYMS 50

                LATB = $38          'Send a single 3 on bus for 4bit mode
                DELAYUS 50
                LATB = $30
                DELAYMS 50

                LATB = $38          'Send a single 3 on bus for 4bit mode
                DELAYUS 50
                LATB = $30
                DELAYMS 50

                LATB = $28          'Send a single 2 on bus for 4bit mode
                DELAYUS 50
                LATB = $20
                DELAYMS 500


'                'Traditional LED script
'                TEMP_LCD = $28
'                GOSUB LCD_CMD_OUT
'                DELAYMS 1

'                TEMP_LCD = $0C
'                GOSUB LCD_CMD_OUT
'                DELAYMS 1

'                TEMP_LCD = $01
'                GOSUB LCD_CMD_OUT
'                DELAYMS 1

'                TEMP_LCD = $06
'                GOSUB LCD_CMD_OUT
'                DELAYMS 10


                'Oled script
                TEMP_LCD = $2A          'Enable internal regulator
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $08
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $71
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $5C
                GOSUB LCD_TEXT_OUT
                DELAYMS 1

                TEMP_LCD = $28
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $08          'Set display off
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $2A          'Set display clock divider
                GOSUB LCD_CMD_OUT
                DELAYMS 1
                                             
                TEMP_LCD = $79
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $D5
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $70
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $78
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $08          'Set display mode
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $06          'Set re-map
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $72          'CG rom management
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $09
                GOSUB LCD_TEXT_OUT
                DELAYMS 1

                TEMP_LCD = $79          'Set oled characterization
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $DA          'Set seg pins
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $10
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $DC          'Set segment low voltage
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $03
                GOSUB LCD_CMD_OUT

                DELAYMS 100             'Vcc power stable

                TEMP_LCD = $81          'Set contrast control
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $FF
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $D9          'Set pre charge period
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $F1
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $DB          'Set VcomH
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $40
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $78          'Exit characterization
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $28
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $08          'Set display off
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $01          'Clear display
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $80          'Set ddram address
                GOSUB LCD_CMD_OUT
                DELAYMS 1

                TEMP_LCD = $0C          'Set display on
                GOSUB LCD_CMD_OUT

                FOR TEMP1 = 1 TO 3      '3 flashes at startup
                    LED = 1
                    DELAYMS 200
                    LED = 0
                    DELAYMS 300
                NEXT

                GOTO MAIN

'=================================================

Config_Start
    FOSC = XT   ' HSHP           ' HS oscillator (high power > 16 MHz)
    PLLCFG = On           ' Oscillator multiplied by 4
    PRICLKEN = On         ' Primary clock enabled
    FCMEN = Off           ' Fail-Safe Clock Monitor disabled
    IESO = Off            ' Internal/External Oscillator Switchover mode disabled
    PWRTEN = On           ' Power up timer enabled
    BOREN = SBORDIS       ' Brown-out Reset enabled in hardware only (SBOREN is disabled)
    BORV = 190            ' Brown Out Reset Voltage set to 1.90 V nominal
    WDTEN = Off           ' Watch dog timer is always disabled. SWDTEN has no effect.
    WDTPS = 128           ' Watchdog Timer Postscale 1:128
    CCP2MX = PORTC1       ' CCP2 input/output is multiplexed with RC1
    PBADEN = Off          ' PORTB<5:0> pins are configured as digital I/O on Reset
    CCP3MX = PORTB5       ' P3A/CCP3 input/output is multiplexed with RB5
    HFOFST = On           ' HFINTOSC output and ready status are not delayed by the oscillator stable status
    T3CMX = PORTC0        ' Timer3 Clock Input (T3CKI) is on RC0
    P2BMX = PORTD2        ' ECCP2 B (P2B) is on RB5
    MCLRE = EXTMCLR       ' MCLR pin enabled, RE3 input pin disabled
    STVREN = Off          ' Stack full/underflow will not cause Reset
    LVP = Off             ' Single-Supply ICSP disabled
    XINST = Off           ' Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
    Debug = Off           ' Disabled
    Cp0 = Off             ' Block 0 (000800-001FFF) not code-protected
    CP1 = Off             ' Block 1 (002000-003FFF) not code-protected
    CP2 = Off             ' Block 2 (004000-005FFF) not code-protected
    CP3 = Off             ' Block 3 (006000-007FFF) not code-protected
    CPB = Off             ' Boot block (000000-0007FF) not code-protected
    CPD = Off             ' Data EEPROM not code-protected
    WRT0 = Off            ' Block 0 (000800-001FFF) not write-protected
    WRT1 = Off            ' Block 1 (002000-003FFF) not write-protected
    WRT2 = Off            ' Block 2 (004000-005FFF) not write-protected
    WRT3 = Off            ' Block 3 (006000-007FFF) not write-protected
    WRTC = Off            ' Configuration registers (300000-3000FF) not write-protected
    WRTB = Off            ' Boot Block (000000-0007FF) not write-protected
    WRTD = Off            ' Data EEPROM not write-protected
    EBTR0 = Off           ' Block 0 (000800-001FFF) not protected from table reads executed in other blocks
    EBTR1 = Off           ' Block 1 (002000-003FFF) not protected from table reads executed in other blocks
    EBTR2 = Off           ' Block 2 (004000-005FFF) not protected from table reads executed in other blocks
    EBTR3 = Off           ' Block 3 (006000-007FFF) not protected from table reads executed in other blocks
    EBTRB = Off           ' Boot Block (000000-0007FF) not protected from table reads executed in other blocks
Config_End

It looks very clunky but I'm not looking for slick - yet. The print command also doesn't work!
I have an old LCD display in parallel to the Oled and can confirm the LCD does show characters so the hardware is ok. I have also put another Oled in parallel just incase any smoke has leaked, but it also doesn't work.

Cheers for looking,
Tim.


SCV

The script is correct from "Oled script" onwards. Don't need the pre-amble prior to this.
Unlike most LCD modules, you cannot change the data bus width in software. There are resistors/links on the rear of the board which define the bus width (move BS0 from L to H.

Pity really, I have a stack of product with the displays fitted...