SSD1306 OLED (72x40) I2C display from scratch


+ Reply to Thread
Results 1 to 40 of 61

Hybrid View

  1. #1
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,865


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (42x40) I2C display from scratch

    These LCD's are difficult to use. Indeed there are too many parameters to set and also you have to design the characters to display.

    The good thing is that you have flexibility in designing the characters, the bad is that you have to do it!

    The good member Richard has done much of the dirty work to use these LCD's and gave us the libraries. But you have to do your part too, especially if you have different LCD. You need to adapt to the dimensions of the screen, design your graphics etc...

    Powering up the display may not light any LED's and display nothing. All are software controlled.

    I tried an 0.9" LCD and with the support of the Richard managed to display text in various sizes. But I admit I have not fully mastered the beast.

    Ioannis

  2. #2
    Join Date
    May 2013
    Location
    australia
    Posts
    2,408


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (42x40) I2C display from scratch

    The latest version of the include is on post #90 of the link posted by ionnis reposted here for your convenience

    this display is not something you can sneak up on easily , you really need a 100% solution before you can get anywhere

    your 42x40 version will very likely need a few tweaks to match the way the oled array has been mapped onto the segment/com pins
    and represented on the graphic memory overlay of the driver chip, i don't have one to experiment with

    there is an alternative version here for p18 chips only that is more versatile, it would still need the same tweaks too
    https://www.picbasic.co.uk/forum/sho...lays-with-PBP3


    the init routine is fairly well commented if you read it in conjunction with the ssd1306 data sheet
    Code:
    '****************************************************************'*  Name    : ssd1306_I2C.INC                                   *
    '*  Author  : richard                                           *
    '*  Notice  :                                                   *
    '*          :                                                   *
    '*  Date    : 8/2/2022                                          *
    '*  Version : 1.2                                               *
    '*                                                              *
    '*                                                              *
    '*  Notes   : font address banksel fixed                        *
    '*          :FOR pic 16/18       SSD1306                        *
    '****************************************************************
     
     goto overglcd
    ; adjust to suit and  place these in main prg
    ;use this define for hw i2c 
    ;#define hwi2c 1 
    ;#DEFINE PIC16 1    ;IF PIC 16 USED  [USE PIC16 FONT TOO}
    ' ssdheight con 7       ; 7 = 8 PAGES  64*128 ,  3 = 4 pages 32*128
    ' ssdwidth  con 127     ; 128 PIXELS WIDE
    ' SCL var PortC.3       ' I2C Clock
    ' SDA var PortC.4       ' I2C Data
    ' sdd1306_addr con $78
     
     USERCOMMAND "GLCDC"     ; X,Y,CHR  0 <  X < 127  ,   0 <  Y < 7    31 < CHR > 127  
     USERCOMMAND "GLCD_CLR"  ;clear area x,y,W,H    
     USERCOMMAND "GLCDSTR"   ;STRING @ X,Y  or   Constant String
     USERCOMMAND "GLCDDHL"   ; x,y,L ,bit-patten
     USERCOMMAND "GLCDDVL"   ; x,y,H
     USERCOMMAND "SSDC"      ;cmd BYTE TO SSD1306
     USERCOMMAND "SSDBM"     ;x,y,w,h,label  
    
    
     ASM  
     
     
     ;----------------------VERT LINE------------------------------------        
    GLCDDVL?CCC  macro Xin ,Yin , Hin 
        MOVE?CB  Xin ,_gx 
        MOVE?CB  Yin,_gy 
        MOVE?CB  Hin ,_gl 
        L?CALL _xyy
        endm 
           
     ;----------------------HORIZ LINE------------------------------------ 
    GLCDDHL?CCCC  macro Xin ,Yin , Win ,Cin
        MOVE?CB  Xin ,_gx 
        MOVE?CB  Yin,_gy 
        MOVE?CB  Win ,_gl
        MOVE?CB  Cin ,_glcdData 
        L?CALL _xyx
        endm  
     
      ;----[const String]---------------------------------------------------------------
    GLCDSTR?CCS  macro Xin ,Yin,Cin 
     IFNDEF  TBLPTRL
        local TheString, OverStr ; define local labels so you can call macro multiple times
        goto OverStr ; goto over string stored in FLASH, so processor can't execute that
    TheString ;label to get address of your string
        da Cin, 0 ;add string to flash at TheString address and end string with 0
    OverStr
        MOVE?CW  TheString, _glcd_bigaddress
        MOVE?CB Xin , _gx
        MOVE?CB Yin , _gy
        L?GOTO  _GlcdUnpackStr
     ELSE  
        local TheString, OverStr ; define local labels so you can call macro multiple times
        goto OverStr ; goto over string stored in FLASH, so processor can't execute that
    TheString ;label to get address of your string
        data Cin, 0 ;add string to flash at TheString address and end string with 0
    OverStr
        movlw   UPPER TheString
        movwf   TBLPTRU
        movlw   HIGH TheString 
        movwf   TBLPTRH
        movlw   LOW TheString
        movwf   TBLPTRL
        MOVE?CB Xin , _gx
        MOVE?CB Yin , _gy
        L?CALL  GLCD_Cstr_out 
     ENDIF     
        endm  
        
         
    SSDBM?CCCCL   macro Xin ,Yin ,Win,Hin,BMin 
     IFNDEF  TBLPTRL
        ERROR BITMAPS ONLY SUPPORTED ON PIC18
     ENDIF
         MOVE?CB Xin , _gx
         MOVE?CB Yin , _gy
         MOVE?CB Hin/8-1 , _gy_
         MOVE?CB Win+Xin-1 , _gx_
         MOVE?CW Win*Hin/8 , _glcd_rad
         banksel   _glcdbm
         movlw low BMin
         movwf _glcdbm
         movlw high BMin
         movwf _glcdbm +1
         BANKSEL 0
         L?CALL  _ssd_bitmap
          endm
    
    
    
    
     ;----------------------Strings------------------------------------
    GLCDSTR?CBB  macro Xin ,Yin ,Bin
        MOVE?CB Xin , _gx
        MOVE?BB Yin , _gy
        MOVE?CB high Bin, FSR1H ;load highbyte 
        MOVE?CB low  Bin, FSR1L ;load low byte
        L?CALL  GLCD_str_out
        endm         
    GLCDSTR?CCB  macro Xin ,Yin ,Bin
        MOVE?CB Xin , _gx
        MOVE?CB Yin  ,_gy
        MOVE?CB high (Bin), FSR1H ;load highbyte 
        MOVE?CB low  (Bin), FSR1L ;load low byte
        L?CALL  GLCD_str_out
        endm              
    GLCDSTR?BBB  macro Xin ,Yin ,Bin
        MOVE?B  Xin, _gx
        MOVE?B  Yin, _gy
        MOVE?CB high Bin, FSR1H ;load highbyte 
        MOVE?CB low  Bin, FSR1L ;load low byte
        L?CALL  GLCD_str_out
        endm 
    GLCDSTR?WBB  macro Xin ,Yin ,Bin
        MOVE?WB Xin, _gx
        MOVE?BB Yin, _gy
        MOVE?CB high Bin, FSR1H ;load highbyte 
        MOVE?CB low  Bin, FSR1L ;load low byte
        L?CALL  GLCD_str_out
        endm  
    GLCDSTR?WWB  macro Xin ,Yin ,Bin
        MOVE?WB Xin, _gx
        MOVE?WB Yin, _gy
        MOVE?CB high Bin, FSR1H ;load highbyte 
        MOVE?CB low  Bin, FSR1L ;load low byte
        L?CALL  GLCD_str_out
        endm 
     
     
    SSDC?C  macro Cin
        MOVE?CB  Cin , _glcdData
        L?CALL   _cmd_byte
       endm 
    SSDC?B  macro Cin
        MOVE?BB  Cin , _glcdData
        L?CALL   _cmd_byte
       endm 
    
    
    GLCD_CLR? macro
        MOVE?CB  0, _gx 
        MOVE?CB  0, _gy 
        MOVE?CB  _ssdwidth, _gx_ 
        MOVE?CB  _ssdheight, _gy_
        L?CALL   _glcd_clrxy
       endm 
    
    
    GLCD_CLR?CCCC macro   Xin ,Yin,X1in ,Y1in
        MOVE?CB  Xin, _gx 
        MOVE?CB  Yin, _gy 
        MOVE?CB  X1in, _gx_ 
        MOVE?CB  Y1in, _gy_
        L?CALL   _glcd_clrxy
       endm 
           
     ;----------------------Character @ X,Y ------------------------------------        
    GLCDC?BBB  macro Xin ,Yin , Bin
        MOVE?BB  Xin, _gx 
        MOVE?BB  Yin, _gy 
        MOVE?BB  Bin, _glcdCh
        L?CALL   _gcga
        endm    
    GLCDC?WBB  macro Xin ,Yin , Bin
        MOVE?WB  Xin, _gx 
        MOVE?BB  Yin, _gy 
        MOVE?BB  Bin, _glcdCh
        L?CALL   _gcga
        endm  
    GLCDC?WWB  macro Xin ,Yin , Bin
        MOVE?WB  Xin, _gx 
        MOVE?WB  Yin, _gy 
        MOVE?BB  Bin, _glcdCh
        L?CALL  _gcga
        endm    
            
    GLCDC?BBC  macro Xin ,Yin , Cin
        MOVE?BB  Xin, _gx 
        MOVE?BB  Yin, _gy 
        MOVE?CB  Cin ,_glcdCh
        L?CALL   _gcga
        endm   
    GLCDC?WBC  macro Xin ,Yin , Cin
        MOVE?WB  Xin, _gx 
        MOVE?BB  Yin, _gy 
        MOVE?CB  Cin ,_glcdCh
        L?CALL   _gcga
        endm
    GLCDC?CCC  macro Xin ,Yin ,Cin
        MOVE?CB  Xin ,   _gx 
        MOVE?CB  Yin,    _gy 
        MOVE?CB  Cin,   _glcdCh
        L?CALL   _gcga 
        endm   
    GLCDC?CCB  macro Xin ,Yin ,Bin
        MOVE?CB  Xin ,  _gx 
        MOVE?CB  Yin,    _gy 
        MOVE?BB  Bin, _glcdCh
        L?CALL   _gcga 
        endm  
    
    
        
       
    GLetAddress macro Label, Wout
        BANKSEL Wout
        movlw low Label          ; get low byte
        movwf Wout
        movlw High Label         ; get high byte
        movwf Wout + 1  
        BANKSEL 0
        endm 
          
     IFDEF    TBLPTRL 
         
    GLCD_Cstr_out
        tblrd   *+
        movf   TABLAT,w
        bz	GLCD_exit_Cstr_out  ; EXIT ON Null char 
        CHK?RP  _glcdCh 
        MOVWF   _glcdCh 
        CHK?RP  _glcd_bigaddress
        movff   TBLPTRU,_glcd_bigaddress
        movff   TBLPTRH,_glcd_bigaddress+1
        movff   TBLPTRL,_glcd_bigaddress+2
        L?CALL  _gcga
        CHK?RP  _glcd_bigaddress
        movff   _glcd_bigaddress   ,TBLPTRU
        movff   _glcd_bigaddress+1 ,TBLPTRH
        movff   _glcd_bigaddress+2 ,TBLPTRL
        bra     GLCD_Cstr_out        
    GLCD_exit_Cstr_out
        BANKSEL 0
        return 
         
    
    
          
    GLCD_str_out
        movf POSTINC1, W	; Get a character
        bz	GLCD_exit_strout  ; EXIT ON Null char 
        CHK?RP  _glcdCh 
        MOVWF _glcdCh
        BANKSEL 0
        L?CALL _gcga  
        bra    GLCD_str_out        
    GLCD_exit_strout
        BANKSEL 0
        return    
     ELSE   
    
    
      
    GLCD_str_out
        IFDEF BSR
            MOVIW FSR1++	; Get a character
            BTFSC STATUS,Z
            BRA	GLCD_exit_strout  ; EXIT ON Null char 
        ELSE
            movf INDF, W	; Get a character
           BTFSC STATUS,Z
            GOTO	GLCD_exit_strout  ; EXIT ON Null char 
            INCF FSR,F 
        ENDIF
        CHK?RP  _glcdCh 
        MOVWF _glcdCh
        MOVE?BB FSR1L,_glcd_bigaddress
        MOVE?BB FSR1H,_glcd_bigaddress+1
        BANKSEL 0
        L?CALL _gcga 
        MOVE?BB _glcd_bigaddress,FSR1L
        MOVE?BB _glcd_bigaddress+1,FSR1H
        GOTO  GLCD_str_out      
    GLCD_exit_strout
        BANKSEL 0
        return     
     ENDIF 
    endasm
        
        glcd_bigaddress  VAR BYTE[3]
        glcd_buff        VAR BYTE[32]
        BIG_TEXT    var byte 
        glcd_rad    var word
        glcdCh      var byte  'chr  DATA
        glcdData    VAR byte  'DATA
        glcdBC      VAR word  'gca  var
        glcdDC      VAR BYTE  'gca  var
        glcdFont    var word  bank0'font address
        glcdOffset  VAR word  'font offset
        glcdbm      VAR word  'bitmap offset
        gl          var byte  'width/height
        gy          var byte  'gca  pg   address
        gy_         var byte  'gca  pg   address
        gx          var byte  'gca  row  address
        gx_         var byte  'gca  row  address
        GRX         var byte  'DATA
        ctemp       var word
        ctemp1      var word
        ssd_add     var byte
        glcdStrAddr var word ext
    @glcdStrAddr =   _glcd_bigaddress 
    
    
    GlcdUnpackStr:     
        readcode glcdStrAddr,CTEMP
        glcd_bigaddress[2]  = CTEMP&$7f
        ctemp=ctemp<<1
        glcdCh = CTEMP.HIGHBYTE 
        glcdStrAddr=glcdStrAddr+1
        if   glcdCh then 
            gosub gcga
            glcdCh =  glcd_bigaddress[2]
        else
            return
        endif
        if   glcdCh then 
            gosub gcga
        else
            return
        endif
        goto   GlcdUnpackStr:     
    return    
        
        
     
    glcd_init: 
    #ifdef hwi2c
        SSPSTAT = 0 'High Speed Filter
        SSPADD = $26'400 kHz @32 MHz
        SSPCON1 = %00101000 'I2C Master Mode Enable
        SSPCON3 = 0
        
    #endif
        @ GLetAddress _font7x5,_glcdFont
        ssd_add = sdd1306_addr 
        SSDc $AE ' Display OFF
        SSDc $d5 
        SSDc $80 
        SSDc $a8 : SSDc $3f 
        SSDc $D3 : SSDc $00 ; Set Display Offset Mode Set 0  
        if ssdheight > 3  then
            SSDc $40   ' Set display start line 0 
        else
            SSDc $60   ' Set display start line 4 
        endif 
        SSDc $8D : SSDc $14 ' Set Charge Pump Internal
        SSDc $20 : SSDc $00 ' Adressing mode Horizontal
        SSDc $A1   ' set segment remap column 127 as start
        SSDc $C8   ' Com Scan Direction, Flip display vertically
        SSDc $DA   ' set COM pins
        if ssdheight > 3  then
            SSDc$12  ' set COM pins = 128x64=$12   
        else
            SSDc$02  ' set COM pins = 128x32=$02
        endif 
        SSDc $81 : SSDc$7F  ' Set brightness to $01 to $FF  ($7F is default, $01 is faint)
        SSDc $DB : SSDc$40  ' Set VCOM Deselect Level
        SSDc $B0  ' Set Page Address From $B0 to $B7 
        SSDc $2e  ; scroll off
        SSDc $A4  ' display ON continue
        SSDc $A6  ' $A6=NORMAL MODE;  $A7=INVERSE MODE
        SSDc $AF  ' Display ON
    return 
    
    
    
    
    xyx:  ;draw HORIZ LINE @X,Y for W len   0<X>127   1<W>127
        FOR GRX = 0 TO 31
            glcd_buff[GRX] = glcdData  ;uses this var to set which bit/s is used to generate line
        NEXT
        gx = gx&ssdwidth
        gx_= gx + gl
        gy = gy&ssdheight
        gy_= gy
        gosub   setxy
        GRX = gl/32
        glcd_rad = 32
        WHILE GRX
            gosub ssd_data
            GRX = GRX-1
        WEND
        glcd_rad = gl//32
        IF glcd_rad  THEN
            gosub ssd_data
        ENDIF
    return 
    
    
    
    
    xyy:       ;draw VERT LINE @X,Y for W len   @X 0<X>127   1<W>7  
        FOR GRX = 0 TO ssdheight
            glcd_buff[GRX] = 255
        NEXT
        gx = gx&ssdwidth
        gx_= gx
        gy = gy&ssdheight
        gy_= gy+GL
        gosub   setxy
        glcd_rad = gl
        gosub ssd_data
    return
          
        
    glcd_clrxy:    ' clear area  x1y1 to x2 y2
        FOR GRX = 0 TO 31
            glcd_buff[GRX] = 0
        NEXT
        CTEMP = (1 + GX_ - GX)*(1 + GY_ -  GY)
        gosub   setxy
        GRX = CTEMP/32
        glcd_rad=32
        WHILE GRX
            gosub ssd_data
            GRX = GRX-1
        WEND
        glcd_rad = CTEMP//32
        IF GRX THEN
            gosub ssd_data
        ENDIF
    return
      
        
    gcga:     ;draw a chr
        GY = gy&ssdheight      
        GY_= gy + BIG_TEXT 
        gx = gx&ssdwidth
        #ifdef PIC16
        glcdOffset = (glcdch-32)*3 + glcdFont  ; point to cga data
        #ELSE
        glcdOffset = (glcdch-32)*6 + glcdFont  ; point to cga data
        #ENDIF
        gosub unpack
        IF BIG_TEXT THEN 
            GOSUB SSD_BIG
            glcd_rad = 24
            gx_= gx + 11
        ELSE
            glcd_rad = 6
            gx_= gx + 5
        ENDIF
        gosub setxy
        gosub ssd_data
        gx = gx_+ 1 + BIG_TEXT 
        IF GX > 121  THEN  gx=0    ;wrap 
    return   
    
    
    ssd_data:   ;send data block
    #ifdef hwi2c
     glcdBC=0
     SSPCON2.0 = 1 ; SEN - Start Condition Enable Bit 
     WHILE SSPCON2.0 = 1 : WEND ; Wait for Start to complete
     SSPBUF = ssd_add ; Move data to SSPBUF
     WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
     While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave 
     SSPBUF = $40 ; Move data to SSPBUF
     WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
     While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave 
     while  glcdBC < glcd_rad
         SSPBUF = glcd_buff[glcdBC] ; Move data to SSPBUF
         WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
         While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave 
         glcdBC=glcdBC+1   
     wend   
     SSPCON2.2 = 1 ; PEN - send stop bit
     While SSPCON2.2 = 1 : Wend ; Wait for SSP to complete
    #else
     i2Cwrite SDA,SCL,ssd_add,[$40,str glcd_buff\ glcd_rad]
    #endif 
    return 
    #ifndef PIC16   
    ssd_bitmap:   ;send graphic block from flash
     gosub setxy
     glcdBC=0
     SSPCON2.0 = 1 ; SEN - Start Condition Enable Bit 
     WHILE SSPCON2.0 = 1 : WEND ; Wait for Start to complete
     SSPBUF = ssd_add ; Move data to SSPBUF
     WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
     While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave 
     SSPBUF = $40 ; Move data to SSPBUF
     WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
     While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave 
     while  glcdBC < glcd_rad
         readcode glcdbm+glcdBC,CTEMP
         SSPBUF = ctemp.LOWBYTE ; Move data to SSPBUF
         WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
         While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
         SSPBUF = ctemp.highBYTE ; Move data to SSPBUF
         WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
         While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave 
         glcdBC=glcdBC+2  
     wend   
     SSPCON2.2 = 1 ; PEN - send stop bit
     While SSPCON2.2 = 1 : Wend ; Wait for SSP to complete
    return  
    #endif        
           
    SSD_BIG:     ;create a big chr from a small one
       for glcddc = 5 to 0 STEP -1
       ctemp = 0
       ctemp1 = 3
       gL = glcd_buff[glcddc]
       for glcdBc = 0 to 7
           IF  GL & 1 THEN ctemp = ctemp|ctemp1
           ctemp1 = ctemp1<<2
           GL = GL>>1
       NEXT
       gL = glcddc*2
       glcd_buff[GL]   =ctemp.LOWBYTE
       glcd_buff[GL+1] =ctemp.LOWBYTE
       glcd_buff[GL+12]=ctemp.HIGHBYTE
       glcd_buff[GL+13]=ctemp.HIGHBYTE
       NEXT
    RETURN
    
    
    unpack:      ;unpack font from flash
       for glcddc = 0 to 2
           GL = glcddc<<1
           readcode glcdOffset,CTEMP
    #ifdef PIC16
           glcd_buff[gl]  = CTEMP&$7f
           ctemp=ctemp<<1
           glcd_buff[gl+1]= CTEMP.HIGHBYTE
           glcdOffset     = glcdOffset + 1 
    #else 
           glcd_buff[gl]  = CTEMP
           glcd_buff[gl+1]= CTEMP.HIGHBYTE 
           glcdOffset     = glcdOffset + 2 
    #endif 
       next
    return
          
        
    cmd_byte:  'send command sequence "glcdData "
    #ifdef hwi2c
     ;hw i2c
     SSPCON2.0 = 1 ; SEN - Start Condition Enable Bit 
     WHILE SSPCON2.0 = 1 : WEND ; Wait for Start to complete
     SSPBUF = ssd_add ; Move data to SSPBUF
     WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
     While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave 
     SSPBUF = 0 ; Move data to SSPBUF
     WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
     While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave 
     SSPBUF = glcdData ; Move data to SSPBUF
     WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
     While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave 
     SSPCON2.2 = 1 ; PEN - send stop bit
     While SSPCON2.2 = 1: Wend ; Wait for SSP to complete
    #else 
     ;soft i2c
       I2Cwrite SDA,SCL,ssd_add,[0,glcdData]
    #ENDIF
    return 
    
    
    
    
    setxy:    ;set PAGE  WINDOW      
        SSDc $22
        SSDc gy
        SSDc gy_
        SSDc $21
        SSDc gx
        SSDc gx_       
    return         
    
    
    
    
    
    
    overglcd :
    Warning I'm not a teacher

  3. #3
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    906


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    Thanks a lot guys 👍

    I'll give it a try this week-end.

    And thanks Richard for condensing the information here
    Roger

  4. #4
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    906


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    Only garbage at this time...but it's alive

    Name:  72x40_first_life.png
Views: 559
Size:  501.7 KB
    Roger

  5. #5
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,865


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (42x40) I2C display from scratch

    Seems that the character size is too big to fit there..

    Ioannis

  6. #6
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    906


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (42x40) I2C display from scratch

    ...still struggeling with the ssd1306's datasheet to understand the "page" concept and how to display things.

    This is the simplest and shortest code I'm working with for now, composed of different sources I found in this forum and also on ARDUINO's one:

    Code:
    ' ====== DESCRIPTION ===============================================================================
    ' Use mini OLED 72x40 pixel display
    
    ' ====== FUSES =====================================================================================
    ' PIC 16F690 Fuses
    ' Internal oscillator  (activate OSCCON register)
    @ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
    
    @ ERRORLEVEL -306
    @ ERRORLEVEL -202
    
    ' ====== REGISTERS =================================================================================
    '             76543210
    OPTION_REG = %10000000 'PORT A&B Pull-Ups disabled (see WPUA & WPUB)
    OSCCON     = %01100000 'Internal RC set to 4MHZ
    'ANSEL      = %00000000 'Select analog inputs Channels 0 to 7 (AN2 + AN4 selected)
    'ANSELH     = %00000000 'Select analog inputs Channels 8 to 11
    'ADCON0     = %10000000 'A/D Module (Bit5:2 select channels 0:11)
    'ADCON1     = %00000000 'A/D control register
    'CM1CON0    = %00000000 'Comparator1 Module is OFF
    'CM2CON0    = %00000000 'Comparator2 Module is OFF
    'INTCON     = %00000000 'INTerrupts CONtrol (TMR0 OFF)
    'TRISA      = %00000000 'Set Input/Output (0 to 5)
    'PORTA      = %00000000 'Ports High/Low (0 to 5)
    'TRISB      = %00000000 'Set Input/Output (4 to 7)
    'PORTB      = %00000000 'Ports High/Low (4 to 7)
    'TRISC      = %00000000 'Set Input/Output (0 to 7)
    'PORTC      = %00000000 'Ports High/Low (0 to 7)
    
    ' ====== DEFINES ===================================================================================
    DEFINE OSC 4
    'DEFINE NO_CLRWDT 1   'Don't waste cycles clearing WDT  
    'DEFINE HSER_CLOERR 1 'Automatic clear overrun error 
    
    ' ====== VARIABLES =================================================================================
    I2CDevice   var byte
    
    SDA         VAR PORTB.4 ' I2C Data
    SCL         VAR PORTB.6 ' I2C Clock
    
    TEXT        VAR BYTE[20]
    LENGTH      VAR BYTE[2]
    DC          VAR Byte    ' "DATA OR COMMAND", $40=DATA; $0=COMMAND --> changed from bit to byte
    LCD_DATA    VAR BYTE   
    COM         VAR BYTE    ' COMMAND
    
    I           VAR BYTE
    J           VAR BYTE
    X           VAR BYTE  'LCD POSITION X(0 TO 127)
    Y           VAR BYTE  'LCD POSITION Y(0 TO 7)
    
    ' ====== INITIALIZE VARIABLES ======================================================================
    I2CDevice = $78
    
    '======= SSD1306 I2C OLED initialization ===========================================================
    COM = $AE : GOSUB SEND_COMMAND ' turn off oled panel
    COM = $D5 : GOSUB SEND_COMMAND ' set display clock divide ratio/oscillator frequency
    COM = $80 : GOSUB SEND_COMMAND ' set divide ratio
    COM = $A8 : GOSUB SEND_COMMAND ' set multiplex ratio
    COM = $27 : GOSUB SEND_COMMAND ' 1/40 duty
    COM = $D3 : GOSUB SEND_COMMAND ' set display offset
    COM = $00 : GOSUB SEND_COMMAND ' not offset
    COM = $AD : GOSUB SEND_COMMAND ' Internal IREF Setting	
    COM = $30 : GOSUB SEND_COMMAND ' --
    COM = $8D : GOSUB SEND_COMMAND ' set Charge Pump enable/disable
    COM = $14 : GOSUB SEND_COMMAND ' set(0x10) disable
    COM = $40 : GOSUB SEND_COMMAND ' set start line address
    COM = $A6 : GOSUB SEND_COMMAND ' set normal display
    COM = $A4 : GOSUB SEND_COMMAND ' Disable Entire Display On
    COM = $A1 : GOSUB SEND_COMMAND ' set segment re-map 128 to 0
    COM = $C8 : GOSUB SEND_COMMAND ' Set COM Output Scan Direction 64 to 0
    COM = $DA : GOSUB SEND_COMMAND ' set com pins hardware configuration
    COM = $12 : GOSUB SEND_COMMAND '
    COM = $81 : GOSUB SEND_COMMAND ' set contrast control register
    COM = $AF : GOSUB SEND_COMMAND ' 
    COM = $D9 : GOSUB SEND_COMMAND ' set pre-charge period
    COM = $22 : GOSUB SEND_COMMAND '
    COM = $DB : GOSUB SEND_COMMAND ' set vcomh
    COM = $20 : GOSUB SEND_COMMAND ' 
    COM = $AF : GOSUB SEND_COMMAND ' turn on oled panel    
    
    ' ====== PROGRAM ===================================================================================
    PAUSE 20
    GOSUB CLEAR_LCD
    GOSUB TITLE
    
    MAIN:
        PAUSE 1000
        GOTO MAIN
    END
    
    ' ====== CLEAR LCD =================================================================================
    CLEAR_LCD:
        FOR J = 0 TO 7 
            FOR I = 0 TO 71 '127
                LCD_DATA = $00 : GOSUB SEND_DATA
            NEXT I
        NEXT J                             
        RETURN 
        
    ' ====== SEND COMMAND ==============================================================================
    SEND_COMMAND:
        dc = $0
        I2CWrite SDA,SCL,I2CDevice,DC,[COM]
        dc = $40
        RETURN 
        
    ' ====== CLEAR LCD =================================================================================
    SEND_DATA:
        DC = $40
        I2CWrite SDA,SCL,I2CDevice,DC,[LCD_DATA]
        RETURN
        
    ' ====== SEND DATA =================================================================================
    FILL:
        FOR J = 0 TO 7
            FOR I = 0 TO 71 '127
                LCD_DATA = $FF : GOSUB SEND_DATA
            NEXT I
        NEXT J
        RETURN
        
    ' ====== TITLE =====================================================================================
    TITLE:
        X = 0 : Y = 0 : GOSUB SET_XY
        FOR I = 0 TO 71 '127
            LOOKUP I,[$00,$40,$60,$50,$7E,$50,$60,$40,$02,$06,$0E,$1E,$3E,$00,$00,$00,_
            $00,$00,$00,$00,$00,$1F,$3F,$60,$60,$60,$60,$60,$60,$3C,$1C,$00,_
            $00,$7F,$7F,$61,$61,$61,$61,$61,$61,$3F,$1E,$00,$00,$1E,$3F,$61,_
            $61,$61,$61,$61,$61,$38,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,_
            $00,$00,$00,$00,$00,$00,$00,$1F,$3F,$60,$60,$60,$60,$60,$60,$3C,_
            $1C,$00,$00,$1E,$3F,$61,$61,$61,$61,$61,$61,$38,$18,$00,$00,$3F,_
            $7F,$60,$18,$06,$06,$18,$60,$7F,$3F,$00,$00,$00,$00,$00,$00,$00,_
            $00,$00,$00,$1C,$63,$41,$5D,$41,$5D,$41,$5D,$41,$5D,$41,$7F,$00],LCD_DATA
            lcd_data = lcd_data rev 8
            GOSUB SEND_DATA
        NEXT I
    
        X = 0 : Y = 1 : GOSUB SET_XY
        for i = 0 to 71 '127
            lookup i,[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,_
            $00,$00,$00,$00,$00,$F8,$FC,$06,$06,$06,$C6,$C6,$C6,$FC,$F8,$00,_
            $00,$FE,$FE,$80,$80,$80,$80,$80,$80,$00,$00,$00,$00,$18,$1C,$86,_
            $86,$86,$86,$86,$86,$FC,$78,$00,$00,$00,$00,$00,$00,$00,$00,$00,_
            $00,$00,$00,$00,$00,$00,$00,$F8,$FC,$06,$06,$06,$C6,$C6,$C6,$FC,_
            $F8,$00,$00,$18,$1C,$86,$86,$86,$86,$86,$86,$FC,$78,$00,$00,$FE,_
            $FE,$00,$00,$00,$00,$00,$00,$FE,$FE,$00,$00,$00,$00,$00,$00,$00,_
            $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00],lcd_data
            lcd_data=lcd_data rev 8
            GOSUB SEND_DATA
        NEXT I
    
        X = 0 : Y = 3 : GOSUB SET_XY
        for i = 0 to 71 '127
            lookup i,[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3C,$7E,$C3,$C3,$C3,$C3,_
            $C3,$C3,$71,$30,$00,$00,$7F,$FF,$C3,$C3,$C3,$C3,$C3,$C3,$C3,$C3,_
            $00,$00,$7F,$FF,$C1,$C1,$C1,$C1,$C1,$C1,$FF,$7F,$00,$00,$7F,$FF,_
            $C3,$C3,$C3,$C3,$C3,$C3,$7E,$3C,$00,$00,$3F,$7F,$C0,$C0,$C0,$C0,_
            $C0,$C0,$70,$30,$00,$00,$FF,$FF,$03,$03,$03,$03,$03,$03,$FF,$FF,_
            $00,$00,$C0,$C0,$C0,$C0,$FF,$FF,$C0,$C0,$C0,$C0,$00,$00,$FF,$FF,_
            $0C,$0C,$03,$03,$00,$00,$FF,$FF,$00,$00,$3F,$7F,$C0,$C0,$C0,$C1,_
            $C1,$C1,$79,$39,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00],lcd_data
            lcd_data=lcd_data rev 8
            GOSUB SEND_DATA
        NEXT I
    
        X = 0 : Y = 4 : GOSUB SET_XY
        for i = 0 to 71 '127
            lookup i,[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$38,$0C,$0C,$0C,$0C,_
            $0C,$0C,$F8,$F0,$00,$00,$F8,$FC,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,_
            $00,$00,$FC,$FC,$80,$80,$80,$80,$80,$80,$FC,$FC,$00,$00,$FC,$FC,_
            $80,$C0,$60,$30,$18,$0C,$04,$00,$00,$00,$F0,$F8,$0C,$0C,$0C,$0C,_
            $0C,$0C,$38,$30,$00,$00,$FC,$FC,$00,$00,$00,$00,$00,$00,$FC,$FC,_
            $00,$00,$0C,$0C,$0C,$0C,$FC,$FC,$0C,$0C,$0C,$0C,$00,$00,$FC,$FC,_
            $00,$00,$00,$00,$C0,$C0,$FC,$FC,$00,$00,$F0,$F8,$0C,$0C,$0C,$8C,_
            $8C,$8C,$F8,$F0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00],lcd_data
            lcd_data=lcd_data rev 8
            GOSUB SEND_DATA
        NEXT I
    
        X = 0 : Y = 5 : GOSUB SET_XY
        for i = 0 to 71 '127
            lookup i,[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1F,$3F,$30,$30,$30,$30,_
            $30,$30,$30,$30,$00,$00,$0F,$1F,$30,$30,$30,$30,$30,$30,$1F,$0F,_
            $00,$00,$1F,$3F,$30,$30,$30,$30,$30,$30,$1F,$0F,$00,$00,$00,$00,_
            $00,$00,$00,$0F,$1F,$30,$30,$30,$30,$30,$30,$1C,$0C,$00,$00,$30,_
            $30,$30,$30,$3F,$3F,$30,$30,$30,$30,$00,$00,$0F,$1F,$30,$30,$30,_
            $30,$30,$30,$1E,$0E,$00,$00,$3F,$3F,$03,$03,$00,$00,$00,$00,$3F,_
            $3F,$00,$00,$1F,$3F,$30,$30,$30,$30,$30,$30,$3F,$1F,$00,$00,$3F,_
            $3F,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00],lcd_data
            lcd_data=lcd_data rev 8
            GOSUB SEND_DATA
        NEXT I
    
        X = 0 : Y = 6 : GOSUB SET_XY
        for i = 0 to 71 '127
            lookup i,[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$FF,$C0,$C0,$C0,$C0,_
            $C0,$C0,$00,$00,$00,$00,$FC,$FE,$03,$03,$03,$03,$03,$03,$FE,$FC,_
            $00,$00,$FF,$FF,$E0,$F0,$D8,$CC,$C6,$C3,$81,$00,$00,$00,$00,$00,_
            $00,$00,$00,$0C,$8E,$C3,$C3,$C3,$C3,$C3,$C3,$7E,$3C,$00,$00,$03,_
            $03,$03,$03,$FF,$FF,$03,$03,$03,$03,$00,$00,$FC,$FE,$03,$03,$03,_
            $63,$63,$63,$7E,$7C,$00,$00,$FF,$FF,$00,$00,$C0,$C0,$30,$30,$FF,_
            $FF,$00,$00,$FF,$FF,$60,$60,$60,$60,$60,$60,$FF,$FF,$00,$00,$FF,_
            $FF,$03,$03,$03,$03,$03,$03,$03,$03,$00,$00,$00,$00,$00,$00,$00],lcd_data
            lcd_data=lcd_data rev 8
            GOSUB SEND_DATA
        NEXT I
        RETURN
        
    '======= SET_XY ====================================================================================
    SET_XY:
        COM = $21 : GOSUB SEND_COMMAND
        COM = X   : GOSUB SEND_COMMAND
        COM = 71  : GOSUB SEND_COMMAND
        COM = $22 : GOSUB SEND_COMMAND
        COM = Y   : GOSUB SEND_COMMAND
        COM = 41  : GOSUB SEND_COMMAND
        RETURN


    Seems that the character size is too big to fit there..
    Originally, this code is made for a larger display so I need to adapt it.
    Roger

  7. #7
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,865


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (42x40) I2C display from scratch

    Is it worth it the effort to spend much time on this LCD's?

    It tried it and seems a lot of waste of time. Also too small for my age

    Ioannis

  8. #8
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    906


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (42x40) I2C display from scratch

    Quote Originally Posted by Ioannis View Post
    These LCD's are difficult to use. Indeed there are too many parameters to set....
    Yes, I agree, this is definitively the hardest part to get it work.

    Richard, how did you come to this $68 value please? I can't figure it out

    Name:  2023-12-12 17_44_38-SSD1306 COMMAND reference.pdf - [SSD1780] - SumatraPDF.png
Views: 257
Size:  23.7 KB



    '======= SSD1306 I2C OLED initialization ================================================== =========
    COM = $AE : GOSUB SEND_COMMAND ' turn off OLED panel
    COM = $D5 : GOSUB SEND_COMMAND ' set display clock divide ratio/oscillator frequency
    COM = $F0 : GOSUB SEND_COMMAND ' set divide ratio
    COM = $A8 : GOSUB SEND_COMMAND ' set multiplex ratio
    COM = $27 : GOSUB SEND_COMMAND ' 1/40 duty
    COM = $D3 : GOSUB SEND_COMMAND ' set display offset
    COM = $00 : GOSUB SEND_COMMAND
    COM = $40 : GOSUB SEND_COMMAND ' set display start line
    COM = $8D : GOSUB SEND_COMMAND ' set Charge Pump enable/disable
    COM = $14 : GOSUB SEND_COMMAND ' set(0x10) disable
    COM = $20 : GOSUB SEND_COMMAND ' Addressing Setting Command Table
    COM = $00 : GOSUB SEND_COMMAND ' Page Addressing Mode
    COM = $A1 : GOSUB SEND_COMMAND ' set segment re-map: column address 127 is mapped to SEG0
    COM = $C8 : GOSUB SEND_COMMAND ' Set COM Output Scan Direction 64 to 0
    COM = $DA : GOSUB SEND_COMMAND ' set com pins hardware configuration
    COM = $12 : GOSUB SEND_COMMAND ' Sequential COM pin configuration
    COM = $AD : GOSUB SEND_COMMAND ' Internal IREF Setting
    COM = $30 : GOSUB SEND_COMMAND ' --
    COM = $81 : GOSUB SEND_COMMAND ' set contrast control register
    COM = $2F : GOSUB SEND_COMMAND ' set contrast value 0..255
    COM = $D9 : GOSUB SEND_COMMAND ' set pre-charge period
    COM = $22 : GOSUB SEND_COMMAND ' set pre-charge value
    COM = $DB : GOSUB SEND_COMMAND ' set vcomh deselect level
    COM = $20 : GOSUB SEND_COMMAND ' set vcomh value
    COM = $A4 : GOSUB SEND_COMMAND ' Disable Entire Display On
    COM = $A6 : GOSUB SEND_COMMAND ' set normal display
    COM = $0C : GOSUB SEND_COMMAND ' set lower column address
    COM = $11 : GOSUB SEND_COMMAND ' set higher column address
    COM = $68 : GOSUB SEND_COMMAND ' set display start line register
    COM = $AF : GOSUB SEND_COMMAND ' turn on OLED panel
    Last edited by flotulopex; - 12th December 2023 at 17:02.
    Roger

  9. #9
    Join Date
    May 2013
    Location
    australia
    Posts
    2,408


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (72x40) I2C display from scratch

    Richard, how did you come to this $68 value please? I can't figure it out
    the info supplied with the display makes calculating the value somewhat difficult . in fact i cannot see the connection at all

    the command basically sets where the memory line representing page 0 bit 0 maps to the physical display top row pixels, it can be vertically offset by 0 to 63 pixels in a virtually identical way to the way the display scrolls horizontally

    it needed to be offset by -23 pixels to get the top row to align with page 0 bit 0

    command range = 0x40 to 0x7f , 0x7f - 23 = 0x68
    Last edited by richard; - 12th December 2023 at 21:23.
    Warning I'm not a teacher

  10. #10
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    906


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    Well, I think I'm just gonna remember this settings "as is".

    Thanks for trying to make things more clear for me
    Roger

  11. #11
    Join Date
    Feb 2013
    Posts
    1,090


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (72x40) I2C display from scratch

    This is very interesting thread, giving me some hope that I will be able to use OLED screens with PBP one day, but I have a quesiton - 24C64 or something like that costs under $1. Why not use it for font storage?

  12. #12
    Join Date
    May 2013
    Location
    australia
    Posts
    2,408


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (72x40) I2C display from scratch

    I have a quesiton - 24C64 or something like that costs under $1. Why not use it for font storage

    because you can save your $1 and another one by buying a better pic to start with and :-

    not have a costlier more complex circuit board .
    use a standard font file generated by glcd font creator.
    its faster, uses hardware i2c and can do proper graphics too.

    as i said at the beginning if you want easy get a pic 18

    Name:  prices.jpg
Views: 228
Size:  173.6 KB
    Last edited by richard; - 16th December 2023 at 04:58.
    Warning I'm not a teacher

  13. #13
    Join Date
    Feb 2013
    Posts
    1,090


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (72x40) I2C display from scratch

    So expensive
    I'm buying 2nd hand 886 and 1829 for about 50 and 90 cents in China
    Since I'm not doing anything commercial, this is just fine for me.

  14. #14
    Join Date
    Feb 2013
    Posts
    1,090


    Did you find this post helpful? Yes | No

    Default Re: SSD1306 OLED (72x40) I2C display from scratch

    And by the way, I don't see any reasons, why you can't write GLCD (which can't save file on windows 10-11) generated or any other software generated font into external EEPROM.

Similar Threads

  1. big char oled display
    By mombasa in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 19th September 2020, 07:02
  2. SSD1306 start display problem
    By harryweb in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 14th December 2016, 19:16
  3. Cannot drive I2C Oled :(
    By elcrcp in forum mel PIC BASIC Pro
    Replies: 21
    Last Post: - 20th August 2016, 12:19
  4. OLED Display Noise problem
    By gunayburak in forum mel PIC BASIC Pro
    Replies: 24
    Last Post: - 5th July 2016, 10:15
  5. Help With OLED Display / 128X64 SSD1306
    By Denner in forum General
    Replies: 6
    Last Post: - 25th May 2013, 15:40

Members who have read this thread : 27

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts