SSD1306 OLED (72x40) I2C display from scratch


+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 61
  1. #1
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891

    Default SSD1306 OLED (72x40) I2C display from scratch

    Hi there,

    I juste received a bunch of very small (72x40) OLED displays driven by a SSD1306 controller.

    Name:  2023-11-13 17_51_05-Mini OLED 72x40 front_200x200.png
Views: 530
Size:  42.6 KBName:  2023-11-13 17_51_51-Mini OLED 72x40 back_200x200.png
Views: 523
Size:  53.3 KB

    I have absolutely never used those displays, in particular the SSD1306 controller.

    After a few searches in the forum, I got some examples but these don't really help unless I first understand the very basics.

    So, would anyone of you have a code snippet I could start with and ready to share it or a good reference to understand the SSD1306 please?

    For example, it starts right at the beginning: there seems to be a "display" address. Is this standard for I2C displays or should I get it from the manufacturer?

    Voilą, that's the low I'm right now...

    So again, if somenone has basic stuff to share, I would really appreciate
    Roger

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


    Did you find this post helpful? Yes | No

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

    I got some examples but these don't really help unless I first understand the very basics.
    i would initialize the display as per my posts to start with and work from there


    there seems to be a "display" address. Is this standard for I2C displays or should I get it from the manufacturer?
    a simple i2c scan such as this will reveal the address

    Code:
    '****************************************************************'*  Name    : UNTITLED.BAS                                      *
    '*  Author  : [select VIEW...EDITOR OPTIONS]                    *
    '*  Notice  : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
    '*          : All Rights Reserved                               *
    '*  Date    : 9/23/2014                                         *
    '*  Version : 1.0                                               *
    '*  Notes   : pic16f1825                                        *
    '*          :  scan i2c bus                                     *
    '****************************************************************
                                
    #CONFIG
       __config _CONFIG1, _WDTE_ON    & _FOSC_INTOSC   &_MCLRE_ON    &_PWRTE_ON 
       __config _CONFIG2,              _LVP_OFF   & _PLLEN_ON
    #ENDCONFIG
             DEFINE OSC 32
             
      DEFINE I2C_SLOW 1
      
         osccon=$70    '8 mhz
             anselA=0        'dig i/o 
             ANSELC=0
          TRISC= %11111111
           TRISA= %11111110
           
      
    
    
    SCL                 var Portc.1                     ' I2C Clock  PortA.3
    SDA                 var Portc.0                     ' I2C Data   PortA.2
    
    
    
    
    
    
    
    
    
    
    
    
    I                   VAR BYTE
    
    
    buff                var byte[10]   
    addr                var byte
    
    
        porta.0=1
        DEFINE DEBUG_REG PORTA
        DEFINE DEBUG_BIT 0      ;  
        DEFINE DEBUG_BAUD 38400
        DEFINE DEBUG_MODE 0     
        pause 2000
        Debug "Start",13 ,10
    
    
    
    
    
    
    addr=$E3
    
    
    
    
    
    
    
    
    for I = $02 to $fe step 2
    I2Cwrite SDA,SCL,i,addr,[0],nak 
    ARRAYWRITE buff[1], [ "found",0]
    Debug str buff , 9  
    Debug "ack ",hex2 i , 13,10
    
    
    nak:
    
    
    Next I
    
    
    
    
    end
    Warning I'm not a teacher

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


    Did you find this post helpful? Yes | No

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

    okay, first step done!

    Name:  2023-11-14 17_59_52-Clipboard.png
Views: 469
Size:  13.5 KB
    Roger

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


    Did you find this post helpful? Yes | No

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

    Richard,

    I'm not sure to find your initialisation example.

    I found the one from Tim (https://www.picbasic.co.uk/forum/sho...nclude-example).

    I'll try this one if it is okay.
    Roger

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


    Did you find this post helpful? Yes | No

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


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


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    Thanks Ioannis.

    I saw them all but there are many files and includes (...) that Tim's example seemed "easier" to start with.

    Not knowing what I really need to keep among them for a start, it's a little bit more confusing.

    I need help so I'll go back to the post you mentionned and (try to) compose/compile what I need to run on a 16F
    Roger

  7. #7
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    I really appreciate anyone's help but maybe to help me get my head out of the myst, could someone roughly tell me at at least how these displays work?

    Appart from the easiest part which is to connect them to ą µC, how does it basically work like:
    - connect it
    - on power-up, initialize it (seems there's a bunch of parameters to send to the display)
    - will it already light-up something (backlight or any dot on the screen?)
    - prepare a bunch of data to actually define the caracters you will want to display in a LOOKUP table
    - call-up and send this or that caracter to display
    - does the display need to be refreshed every x time or is it a one-shot command that will suffice to have something displayed
    ....

    When I mean "basics", I really mean it.... I have absolutely no clue how this little things work....
    Roger

  8. #8
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,807


    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

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


    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

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


    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

  11. #11
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    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: 422
Size:  501.7 KB
    Roger

  12. #12
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,807


    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

  13. #13
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    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

  14. #14
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,807


    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

  15. #15
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    Up to now, I couldn't find any pixel map for the 72x40 display so I'm relying on information for the 128x64 one.

    This is the information I have found in the 72x40 datasheet:
    Name:  72x40_segments-coms.png
Views: 400
Size:  11.8 KB

    Can anybody tell me how I should convert this in "pages" if I have to do so? I don't understand how data has to be displayed...

    This is the example from the 128x64's datasheet (to be found in attachment):
    Name:  128x64.png
Views: 403
Size:  71.4 KB
    Attached Images Attached Images
    Roger

  16. #16
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

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

    Some comments
    is the display 72x40 of 42x40 ? you describe it both ways
    the write window should be set to width and page height you require and the pixel/page offset to begin write from for proper operation

    and

    with your attempted title page transmission, sending every byte of data like that as individual senddata transactions is extremely inefficient the entire thing could be sent as a single data block in half the time



    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 = 000000 'PORT A&B Pull-Ups disabled (see WPUA & WPUB)
    OSCCON     = 100000 'Internal RC set to 4MHZ
    'ANSEL      = 000000 'Select analog inputs Channels 0 to 7 (AN2 + AN4 selected)
    'ANSELH     = 000000 'Select analog inputs Channels 8 to 11
    'ADCON0     = 000000 'A/D Module (Bit5:2 select channels 0:11)
    'ADCON1     = 000000 'A/D control register
    'CM1CON0    = 000000 'Comparator1 Module is OFF
    'CM2CON0    = 000000 'Comparator2 Module is OFF
    'INTCON     = 000000 'INTerrupts CONtrol (TMR0 OFF)
    'TRISA      = 000000 'Set Input/Output (0 to 5)
    'PORTA      = 000000 'Ports High/Low (0 to 5)
    'TRISB      = 000000 'Set Input/Output (4 to 7)
    'PORTB      = 000000 'Ports High/Low (4 to 7)
    'TRISC      = 000000 'Set Input/Output (0 to 7)
    'PORTC      = 000000 '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
    ;seems a pointless waste if a variable
    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
    ; you assume display is mapped from page 0  , this may not be correct ans could be  0,1,2,3
    
    
    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 
    ;  cant see this working without setting a "window" to write into properly
        
    ' ====== SEND COMMAND ==============================================================================
    SEND_COMMAND:
        dc = $0
        I2CWrite SDA,SCL,I2CDevice,DC,[COM]
        dc = $40
        RETURN 
    
    ; why not just
    SEND_COMMAND:
    I2CWrite SDA,SCL,I2CDevice,[0,COM]
       RETURN  
    
     
    ' ====== CLEAR LCD =================================================================================
    SEND_DATA:
        DC = $40
        I2CWrite SDA,SCL,I2CDevice,DC,[LCD_DATA]
        RETURN
     ; why not just
    SEND_COMMAND:
    I2CWrite SDA,SCL,I2CDevice,[$40,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
     ;  cant see this working without setting a "window" to write into properly  
    ' ====== TITLE =====================================================================================
    ;here you set 6 pages "Y" of data from page 0 to 7  with page 2 missing when a 40 pixel height can have 5 pages maximum
    
    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
    ;attempt to set page to 41 when it cannot be > than 5 pages
    
    
        RETURN
    Last edited by richard; - 19th November 2023 at 23:53.
    Warning I'm not a teacher

  17. #17
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    It's definitively a 72x40 pixel display.

    Thanks Richard for pointing to all changes (and tips) I can/should make in the code

    Now, regarding the way to display data, I still don't get it; I'm completely lost since I have no clue how to do it.

    I'm mostly using serial "common" LCDs in text mode so I don't have to create any font or so.

    In my case, I will use this LCD to display, as big as possible, a number as a percentage (0.0%...99.9%).

    What is the approach? I have a display 72 pixels wide and 40 pixels high (= 2'880 pixels). I assume, the display is divided in what they call "pages" and I should write a data table (LOOKUP) for each page. Is this correct?

    But how do I address the pages? Do I have to do so? Is there a way to send "text" to the display like common LCDs? Is there a way to "design" a font that will in big appear all over the entire display?

    I'm missing fundamentals 😔
    Roger

  18. #18
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

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

    Basically the display is 360 bytes of ram where every bit is a oled, the ram is divided into 5 pages each of 72 bytes
    the 5 pages are overlaid onto a larger array that is 8 pages of 128 bytes, precisely where is not known to me [i have never seen one of those modules]
    the ssd1306 is very versatile and allows vertical and horiz offsets to be set along with scan direction and various mem access methods to suit you.
    to write to a byte you must address its x and y position , the width to be written and number of pages is also expected to be set

    ie to write a 10x14 chr 14 high 10 wide at page 1 posn 12

    SET_XY:
    COM = $21 : GOSUB SEND_COMMAND
    COM = 12 : GOSUB SEND_COMMAND ;x=12
    COM = 22 : GOSUB SEND_COMMAND ;12+10
    COM = $22 : GOSUB SEND_COMMAND
    COM = 1 : GOSUB SEND_COMMAND ;y=1
    COM = 2 : GOSUB SEND_COMMAND ;1+1
    RETURN
    then send the 20 bytes needed to represent your chr


    In my case, I will use this LCD to display, as big as possible, a number as a percentage (0.0%...99.9%).
    easy you need to create a big font with the chrs you need in it


    Is there a way to send "text" to the display like common LCDs?
    no not even close

    if you want easy use a pic18 and my code from here

    where you can define the screen size and create fonts as you need

    or use an enhanced core pic16 and my earlier code that can do double size chrs
    Last edited by richard; - 20th November 2023 at 09:28.
    Warning I'm not a teacher

  19. #19
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    Thanks a lot Richard.

    The fog lifts somehow a little bit....

    I'll give it a try with y 18F 👍
    Last edited by flotulopex; - 20th November 2023 at 09:36.
    Roger

  20. #20
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

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

    is this more clear ?
    draws a 7x5 chr A and 14x10 A in a 72x40 window located @ x=0y=0 after clearing screen [ outside of window is just random noise ]

    here's a pic on a 128x64 screen , there is no telling how it line up for your screen
    Name:  sd1306.jpg
Views: 386
Size:  512.8 KB






    #CONFIG __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOD_ON & _IESO_ON & _FCMEN_ON
    #ENDCONFIG




    define OSC 8




    OSCCON = 110000 'Internal RC set to 8MHZ
    'ANSEL = 000000 'Select analog inputs Channels 0 to 7 (AN2 + AN4 selected)
    'ANSELH = 000000 'Select analog inputs Channels 8 to 11


    'TRISB = 000000 'Set Input/Output (4 to 7)
    'PORTB = 000000 'Ports High/Low (4 to 7)








    ' ====== VARIABLES ================================================== ===============================
    I2CDevice var byte


    SDA VAR PORTB.6 ' I2C Data
    SCL VAR PORTB.4 ' I2C Clock






    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 = $3F : GOSUB SEND_COMMAND ' 1/40 duty
    COM = $D3 : GOSUB SEND_COMMAND ' set display offset
    COM = $0 : GOSUB SEND_COMMAND
    COM = $20 : GOSUB SEND_COMMAND
    COM = $0 : GOSUB SEND_COMMAND
    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 = $7F : 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 = $40 : GOSUB SEND_COMMAND '
    COM = $AF : GOSUB SEND_COMMAND ' turn on oled panel


    ' ====== PROGRAM ================================================== =================================


    GOSUB CLEAR_LCD


    MAIN:
    ;7x5 "A"
    X = 15 : Y = 0 : GOSUB SET_7
    I2CWrite SDA,SCL,I2CDevice,[$40,$fc,$12,$12,$12,$fc]
    ;14x10 "A"
    X = 15 : Y = 2 : GOSUB SET_14
    I2CWrite SDA,SCL,I2CDevice,[$40,$f0,$f8,12,12,14,14,12,12,$f8,$f0_
    ,$ff,$ff,6,6,6,6,6,6,$ff,$ff]
    PAUSE 1000
    GOTO MAIN
    END


    ' ====== CLEAR LCD ================================================== ===============================
    CLEAR_LCD:
    COM = $21 : GOSUB SEND_COMMAND
    COM = 0 : GOSUB SEND_COMMAND
    COM = 71 : GOSUB SEND_COMMAND
    COM = $22 : GOSUB SEND_COMMAND
    COM = 0 : GOSUB SEND_COMMAND
    COM = 4 : GOSUB SEND_COMMAND
    LCD_DATA = $00
    FOR J = 0 TO 4
    FOR I = 0 TO 71
    I2CWrite SDA,SCL,I2CDevice,[$40,LCD_DATA]
    NEXT I
    NEXT J
    RETURN

    ' ====== SEND COMMAND ================================================== ============================
    SEND_COMMAND:
    I2CWrite SDA,SCL,I2CDevice,[0,COM]
    RETURN



    '======= SET_XY ================================================== ==================================
    SET_7: '7x5
    COM = $21 : GOSUB SEND_COMMAND
    COM = X : GOSUB SEND_COMMAND
    COM = x+4 : GOSUB SEND_COMMAND
    COM = $22 : GOSUB SEND_COMMAND
    COM = Y : GOSUB SEND_COMMAND
    COM = y : GOSUB SEND_COMMAND
    RETURN
    SET_14: ;14x10
    COM = $21 : GOSUB SEND_COMMAND
    COM = X : GOSUB SEND_COMMAND
    COM = x+9 : GOSUB SEND_COMMAND
    COM = $22 : GOSUB SEND_COMMAND
    COM = Y : GOSUB SEND_COMMAND
    COM = y+1 : GOSUB SEND_COMMAND
    RETURN
    Last edited by richard; - 22nd November 2023 at 02:14.
    Warning I'm not a teacher

  21. #21
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

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

    Thanks a lot Richard.

    I'll give it a try asap
    Roger

  22. #22
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    Voilą.

    As no caracter would display, I changed the fill caracter in the CLEAR routine to make someting visible.

    Name:  Oled.png
Views: 376
Size:  394.1 KB

    Code:
    ' ====== CLEAR LCD =================================================================================
    CLEAR_LCD:
        COM = $21 : GOSUB SEND_COMMAND ' set column address
        COM = 0   : GOSUB SEND_COMMAND ' column start address
        COM = 71  : GOSUB SEND_COMMAND ' column end address
        COM = $22 : GOSUB SEND_COMMAND ' set page address
        COM = 0   : GOSUB SEND_COMMAND ' page start address
        COM = 4   : GOSUB SEND_COMMAND ' page end address
        FOR J = 0 TO 4
            FOR I = 0 TO 71
                I2CWrite SDA,SCL,I2CDevice,[$40,$FF]
            NEXT I
        NEXT J
        RETURN
    Roger

  23. #23
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    BTW, the number of pixels displayed is 50x20

    Name:  OLED detail.png
Views: 388
Size:  159.1 KB
    Roger

  24. #24
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

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

    are you using my exact code ?
    there are many changes from your orig code including swapping over the scl/sda pins to suit my dev board

    i doubt the pullup resistors are needed most modules have then already installed


    change
    COM = $40 : GOSUB SEND_COMMAND ' set start line address
    to
    COM = $67 : GOSUB SEND_COMMAND ' set start line address
    it looks like display is mapped onto last 5 pages of ram array
    Warning I'm not a teacher

  25. #25
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

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

    Are you using my exact code ?
    Absolutely!

    With this "untouched" code, I get this display:
    Name:  org_code_.png
Views: 364
Size:  372.0 KB

    Then, with the new value of $67, here is what I get:
    Name:  org_code_.png
Views: 369
Size:  389.5 KB
    Roger

  26. #26
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

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

    try this, looking for full white screen

    re pull up resistors for i2c bus , looking at the pic in post #1 that module has none on board , every other module i can find on ebay etc has resistors on board
    so you might need them after all


    Code:
    #CONFIG  __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOD_ON & _IESO_ON & _FCMEN_ON
    #ENDCONFIG
    define OSC 8
    OSCCON = 10000 'Internal RC set to 8MHZ
    ' ====== VARIABLES ================================================== ===============================
    I2CDevice var byte
    SDA VAR PORTB.6 ' I2C Data
    SCL VAR PORTB.4 ' I2C Clock
    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 = $3F : GOSUB SEND_COMMAND ' 1/40 duty
    COM = $D3 : GOSUB SEND_COMMAND ' set display offset
    COM = $0 : GOSUB SEND_COMMAND
    COM = $20 : GOSUB SEND_COMMAND
    COM = $0 : GOSUB SEND_COMMAND
    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 = $68 : 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 = $7F : 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 = $40 : GOSUB SEND_COMMAND '
    COM = $AF : GOSUB SEND_COMMAND ' turn on oled panel
    
    
    ' ====== PROGRAM ================================================== =================================
    
    
    GOSUB CLEAR_LCD
    MAIN:
    ';7x5 "A"
    'X = 15 : Y = 0 : GOSUB SET_7
    'I2CWrite SDA,SCL,I2CDevice,[$40,$fc,$12,$12,$12,$fc]
    ';14x10 "A"
    'X = 15 : Y = 2 : GOSUB SET_14
    'I2CWrite SDA,SCL,I2CDevice,[$40,$f0,$f8,12,12,14,14,12,12,$f8,$f0_
    ',$ff,$ff,6,6,6,6,6,6,$ff,$ff]
    PAUSE 1000
    GOTO MAIN
    END
    ' ====== CLEAR LCD ================================================== ===============================
    CLEAR_LCD:
    COM = $21 : GOSUB SEND_COMMAND
    COM = 20 : GOSUB SEND_COMMAND
    COM = 91 : GOSUB SEND_COMMAND
    COM = $22 : GOSUB SEND_COMMAND
    COM = 0 : GOSUB SEND_COMMAND
    COM = 4 : GOSUB SEND_COMMAND
    LCD_DATA = $ff
    FOR J = 0 TO 4
    FOR I = 0 TO 71
    I2CWrite SDA,SCL,I2CDevice,[$40,LCD_DATA]
    NEXT I
    NEXT J
    RETURN
    ' ====== SEND COMMAND ================================================== ============================
    SEND_COMMAND:
    I2CWrite SDA,SCL,I2CDevice,[0,COM]
    RETURN
    '======= SET_XY ================================================== ==================================
    SET_7: '7x5
    COM = $21 : GOSUB SEND_COMMAND
    COM = X : GOSUB SEND_COMMAND
    COM = x+4 : GOSUB SEND_COMMAND
    COM = $22 : GOSUB SEND_COMMAND
    COM = Y : GOSUB SEND_COMMAND
    COM = y : GOSUB SEND_COMMAND
    RETURN
    SET_14: ;14x10
    COM = $21 : GOSUB SEND_COMMAND
    COM = X : GOSUB SEND_COMMAND
    COM = x+9 : GOSUB SEND_COMMAND
    COM = $22 : GOSUB SEND_COMMAND
    COM = Y : GOSUB SEND_COMMAND
    COM = y+1 : GOSUB SEND_COMMAND
    RETURN
    Last edited by richard; - 24th November 2023 at 20:16.
    Warning I'm not a teacher

  27. #27
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    Thanks Richard.

    This it looks now, with your code ni post #26.


    https://drive.google.com/file/d/1Ud4...usp=drive_link
    Roger

  28. #28
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    These few changes will fill the whole screen in white.

    Code:
    ' ====== CLEAR LCD ================================================== ===============================
    CLEAR_LCD:
    COM = $21 : GOSUB SEND_COMMAND
    COM = 28 : GOSUB SEND_COMMAND
    COM = 99 : GOSUB SEND_COMMAND '91
    COM = $22 : GOSUB SEND_COMMAND
    COM = 0 : GOSUB SEND_COMMAND
    COM = 4 : GOSUB SEND_COMMAND
    LCD_DATA = $ff
    FOR J = 0 TO 4
    FOR I = 28 TO 99
    I2CWrite SDA,SCL,I2CDevice,[$40,LCD_DATA]
    NEXT I
    NEXT J
    RETURN
    Last edited by flotulopex; - 24th November 2023 at 22:19.

  29. #29
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

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

    ok, then this should be pretty close

    Code:
    #CONFIG  __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOD_ON & _IESO_ON & _FCMEN_ON
    #ENDCONFIG
    define OSC 8
    OSCCON = %01110000 'Internal RC set to 8MHZ
    ' ====== VARIABLES ================================================== ===============================
    I2CDevice var byte
    SDA VAR PORTB.6 ' I2C Data
    SCL VAR PORTB.4 ' I2C Clock
    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)
    hshift con 28
    ' ====== 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 = $3F : GOSUB SEND_COMMAND ' 1/40 duty
    COM = $D3 : GOSUB SEND_COMMAND ' set display offset
    COM = $0 : GOSUB SEND_COMMAND
    COM = $20 : GOSUB SEND_COMMAND
    COM = $0 : GOSUB SEND_COMMAND
    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 = $68 : 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 = $7F : 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 = $40 : GOSUB SEND_COMMAND '
    COM = $AF : GOSUB SEND_COMMAND ' turn on oled panel
    
    
    ' ====== PROGRAM ================================================== =================================
    
    
    GOSUB CLEAR_LCD
    MAIN:
    ;7x5 "A"
    X = 15 : Y = 0 : GOSUB SET_7
    I2CWrite SDA,SCL,I2CDevice,[$40,$fc,$12,$12,$12,$fc]
    ;14x10 "A"
    X = 15 : Y = 2 : GOSUB SET_14
    I2CWrite SDA,SCL,I2CDevice,[$40,$f0,$f8,12,12,14,14,12,12,$f8,$f0_
    ,$ff,$ff,6,6,6,6,6,6,$ff,$ff]
    PAUSE 1000
    GOTO MAIN
    END
    ' ====== CLEAR LCD ================================================== ===============================
    CLEAR_LCD:
    COM = $21 : GOSUB SEND_COMMAND
    COM = hshift : GOSUB SEND_COMMAND
    COM = 71 + hshift : GOSUB SEND_COMMAND
    COM = $22 : GOSUB SEND_COMMAND
    COM = 0 : GOSUB SEND_COMMAND
    COM = 4 : GOSUB SEND_COMMAND
    LCD_DATA = 0
    FOR J = 0 TO 4
    FOR I = 0 TO 71
    I2CWrite SDA,SCL,I2CDevice,[$40,LCD_DATA]
    NEXT I
    NEXT J
    RETURN
    ' ====== SEND COMMAND ================================================== ============================
    SEND_COMMAND:
    I2CWrite SDA,SCL,I2CDevice,[0,COM]
    RETURN
    '======= SET_XY ================================================== ==================================
    SET_7: '7x5
    COM = $21 : GOSUB SEND_COMMAND
    COM = X+hshift : GOSUB SEND_COMMAND
    COM = x+hshift+4 : GOSUB SEND_COMMAND
    COM = $22 : GOSUB SEND_COMMAND
    COM = Y : GOSUB SEND_COMMAND
    COM = y : GOSUB SEND_COMMAND
    RETURN
    SET_14: ;14x10
    COM = $21 : GOSUB SEND_COMMAND
    COM = X+hshift: GOSUB SEND_COMMAND
    COM = x+hshift+9 : GOSUB SEND_COMMAND
    COM = $22 : GOSUB SEND_COMMAND
    COM = Y : GOSUB SEND_COMMAND
    COM = y+1 : GOSUB SEND_COMMAND
    RETURN
    Warning I'm not a teacher

  30. #30
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

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

    the google drive link is a dud
    Warning I'm not a teacher

  31. #31
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    I also adjusted your code as:
    Code:
    ' ====== PROGRAM ================================================== =================================
    GOSUB CLEAR_LCD
    
    MAIN:
        '7x5 "A"
        X = 28 : Y = 0 : GOSUB SET_7
        I2CWrite SDA,SCL,I2CDevice,[$40,$fc,$12,$12,$12,$fc]
        
        '14x10 "A"
        X = 28 : Y = 2 : GOSUB SET_14
        I2CWrite SDA,SCL,I2CDevice,[$40,$f0,$f8,12,12,14,14,12,12,$f8,$f0_
        ,$ff,$ff,6,6,6,6,6,6,$ff,$ff]
        PAUSE 1000
        GOTO MAIN
    END
    Name:  WhatsApp Image 2023-11-24 at 23.38.15.jpeg
Views: 370
Size:  72.6 KB
    Roger

  32. #32
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

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

    the google drive link is a dud
    Sorry for that.

    How do I post a small video then?
    Roger

  33. #33
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

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

    Roger

  34. #34
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

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

    link worked.


    all you need to do now is
    1 create a 14x10 font with the chrs you need
    2 workout an efficient way to store and retrieve the font
    3 develop a nice way to plonk it on the screen

    easy as pie
    ps
    if you only need numbers and "%" ,"." it could fit on a 16f690 easily




    hint , pic16 flash memory is 14 bits wide, the ssd1306 can fill memory in vertical mode too
    Last edited by richard; - 24th November 2023 at 23:15.
    Warning I'm not a teacher

  35. #35
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

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

    Thank you so much Richard!!!

    I'll give it a try to create a super big font.

    Let you know for any progress in the next days
    Roger

  36. #36
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

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

    First look at what it could look like

    Name:  000.png
Views: 312
Size:  370.0 KB
    Roger

  37. #37
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,807


    Did you find this post helpful? Yes | No

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

    It looks great!

    Well done Roger!

    Ioannis

  38. #38
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

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

    ...credits are all for Richard
    Roger

  39. #39
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

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

    something to consider about fonts
    it looks like you want 40x22 size font
    a pic16 has a flash word size of 14 bits therefore a font that size
    will take if encoded horizontally by row take 2x40 words per chr
    it will take 3x22 words if encoded vertically by column a reasonable saving.

    one of the benefits of the ssd1306 controller is that it can address its graphics ram either way with ease
    Name:  fonts.jpg
Views: 297
Size:  197.5 KB
    Warning I'm not a teacher

  40. #40
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default SSD1306 OLED (72x40) I2C display from scratch

    Richard,

    I'm still trying to understand your previous post but just for now, there's a question burning my mind: how do I address the display pixel by pixel?
    Roger

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 : 26

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