SSD1306 Include example


+ Reply to Thread
Results 1 to 12 of 12
  1. #1
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default SSD1306 Include example

    Just finished an Include for the SSD1306 mono graphics display. No graphics just text. Best part is that it fits within a 4K chip. Tested on 2 different displays. If you can't get it to work I would suggest making sure you get random bits after the SSD_Init is finished. If you don't see random bits, either your I2C is wrong or you need to spend more time tweaking the SSD_Init. In my case one display refuses to work with a charge pump the other one requires it.

    Regards
    TimC

    Code:
    'SSD 1306 Sample 
    '==========================MCU SETUP============================================
    DEFINE OSC 20
    'OPTION_REG=0 'only for 16F877A
    ADCON0=0
    ADCON1=7
    
    Include "N:\PIC\PicBasicPro\include\SSD1306.inc"  ' bring it in 
    
    '==========================    MAIN  Routine    ==============================
    temp var byte
    
    gosub SSD_Init
    looper:
    
    arraywrite SSD_BUFF,[0,0,"Line 0",0] : gosub SSD_PRINTXY
    arraywrite SSD_BUFF,[" and more",0] : gosub SSD_PRINT	' continue on same line
    
    arraywrite SSD_BUFF,[30,1,"Middle 1",0] : gosub SSD_PRINTXY
    arraywrite SSD_BUFF,[10,2,"Here we are Line 2",0] : gosub SSD_PRINTXY
    random temp		' jumps about
    'temp = 76
    arraywrite SSD_BUFF,[0,3,"Current Temp=",dec2 temp, "deg" ,0] : gosub SSD_PRINTXY
    
    arraywrite SSD_BUFF,[20,5,"Hip Hop Hi Ho 5",0] : gosub SSD_PRINTXY
    arraywrite SSD_BUFF,[10,6,"|%+-./\<=>_     6",0] : gosub SSD_PRINTXY
    arraywrite SSD_BUFF,[10,7,"{}[][email protected]#$%^&*()  7",0] : gosub SSD_PRINTXY
    
    sleep 5
    GOTO looper
    END
    Now The Include

    Code:
    'This code is for driving an OLED screen
    
    'Typical screen is 0.96" 128x64 mono SSD1306 chip with I2C protocol
    'This code has a large char library in it, so it takes some space, you may
    'delete the top and bottom tables if you need more space for your program but
    'you will need to rewrite the logic.
    'No bitmap drawing! Only intended to write text on screen.
    '
    'Screen contains 8 lines (which are 8 pixel height) and 128 columns
    
    ' Typical way to print a formatted line to the DDS1306 Display is like this:
    ' arraywrite SSD_BUFF,[0,3,"Current Temp=",dec2 temp, "deg" ,0] : gosub SSD_PRINTXY
    ' 0= Column in pixels
    ' 3= Row to print on
    ' Last 0 is necessary and to terminate the string to print
    
    ' Public variables and Functions are in the Format SSD_AAAAAA
    ' Private variables and Functions look like SSD_i_AAAAA
    
    '===================  SSD1306  ADDRESS  AND CONSTANTS   ========================
    SSD_i_Device CON $78      ' Normally $78
    SSD_i_DeviceCommand	CON	$00
    SSD_i_DataCommand	CON	$40
    '=========================   SSD Variables   ==================================
    SCL var PortC.3         ' I2C Clock  PortC.3  move if using more than one I2C device
    SDA var PortC.4         ' I2C Data   PortC.4  move if using more than one I2C device
    SSD_BUFF VAR BYTE[27]	' pass through to Display
    SSD_i_Byte2Send		VAR BYTE	' Prepared byte to be sent to Display
    SSD_i_Byte2Send2	VAR BYTE	' Prepared Byte to be sent to Display
    
    SSD_i_Column VAR BYTE' LCD Column POSITION (0 TO 127)
    SSD_i_Row VAR BYTE'LCD Line POSITION FOR PAGE MODE(0 TO 7)
    
    SSD_i_CharIndex var word 'Char codes index
    SSD_i_CharIndexT var byte 'char codes index temp
    SSD_i_OffsetTemp var byte	' calculating offset into tables
    
    SSD_i_StringWork var byte 'index for text
    SSD_i_Char2send var byte 'data carrier for text chars
    
    goto SSD1306_i_Around	' this is an add-in so go around
    
    '====================   SSD1306 initialization   ===============================
    SSD_Init:
    pause 10
    SSD_i_Byte2Send=$AE:GOSUB SSD_i_SendCommand 'Display OFF
    SSD_i_Byte2Send=$D3:SSD_i_Byte2Send2=$00:GOSUB SSD_i_SendCommand2 ' Set offset to 0
    'SSD_i_Byte2Send=$40:GOSUB SSD_i_SendCommand ' Set display start line 0, usually not needed
    SSD_i_Byte2Send=$8D:SSD_i_Byte2Send2=$14:GOSUB SSD_i_SendCommand2 ' Set Charge Pump Internal, usually needed
    SSD_i_Byte2Send=$20:SSD_i_Byte2Send2=$10:GOSUB SSD_i_SendCommand2 ' Adressing mode $10=Page, $00=Horizontal
    SSD_i_Byte2Send=$A1:GOSUB SSD_i_SendCommand	' set segment remap column 127 as start
    SSD_i_Byte2Send=$C8:GOSUB SSD_i_SendCommand ' Com Scan Direction, Flip display vertically
    SSD_i_Byte2Send=$DA:SSD_i_Byte2Send2=$12:GOSUB SSD_i_SendCommand2 ' set COM pins = 128x64=$12   128x32=$02
    SSD_i_Byte2Send=$81:SSD_i_Byte2Send2=$7F:GOSUB SSD_i_SendCommand2 ' Set contrast to $01 to $FF  ($7F is default, $01 is faint)
    SSD_i_Byte2Send=$A4:GOSUB SSD_i_SendCommand ' display ON continue
    SSD_i_Byte2Send=$A6:GOSUB SSD_i_SendCommand ' $A6=NORMAL MODE;  $A7=INVERSE MODE
    SSD_i_Byte2Send=$AF:GOSUB SSD_i_SendCommand 'Display ON
    pause 500	'  look for random bytes. Remove if you would like
    GOSUB SSD_Clear
    return
    '======================Print Lines==============================================
    SSD_Print:
    SSD_i_StringWork = 0	' set index to beginning
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]	' pull letter out of array
    	gosub SSD_i_BuildChar		' Build char and send out
    	SSD_i_StringWork = SSD_i_StringWork + 1		' point to next char
    loop
    return
    
    SSD_PrintXY:
    SSD_i_Column=SSD_BUFF[0]  ' Column in first position
    SSD_i_Row=SSD_BUFF[1]   ' Row in second
    gosub SSD_i_SetXY		' set cursor position
    SSD_i_StringWork = 2			' now point to first character to print
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]
    	gosub SSD_i_BuildChar
    	SSD_i_StringWork = SSD_i_StringWork + 1
    loop
    return
    
    '=====================  Send data  =============================================
    SSD_i_SendData:
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,SSD_i_Byte2Send]
    RETURN
    '====================  Send Command  ===========================================
    SSD_i_SendCommand:
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DeviceCommand,SSD_i_Byte2Send]
    RETURN
    '====================  Send Command  ===========================================
    SSD_i_SendCommand2:
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DeviceCommand, SSD_i_Byte2Send, SSD_i_Byte2Send2]
    RETURN
    '============================== clear ========================================
    SSD_Clear:
    SSD_i_Column=0
    'SSD_i_Row=0
    FOR SSD_i_Row=0 TO 7
        gosub SSD_i_SetXY
        FOR SSD_i_OffsetTemp=0 TO 127
        	I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,0]	'Send 0 to every column in every line
            'GOSUB SSD_i_SendData
        NEXT SSD_i_OffsetTemp
    NEXT SSD_i_Row
    SSD_i_Column=0 : SSD_i_Row=0 : gosub SSD_i_SetXY	' Go Home
    RETURN
    '===========================================SET X AND Y=========================
    SSD_i_SetXY:
    SSD_i_Byte2Send=$21:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Column:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=127:GOSUB SSD_i_SendCommand
    'Above 3 lines means; Column starts at SSD_i_Column and End at 127
    SSD_i_Byte2Send=$22:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Row:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Row:GOSUB SSD_i_SendCommand
    'Above 3 lines means; Line starts at SSD_i_Row and end at SSD_i_Row,
    'which means ; Only work on specified line!
    RETURN
    '===================== Build Character and Send=====================================
    SSD_i_BuildChar:
    ' Enter this Subroutine with printable character: SSD_i_Char2send
    ' SSD_i_Char2send is subtracted from " " (space char) and * by 5 to be able to index into one table
    ' One table is broken into 3 to avoid the 255 max.  Index into table must be a byte variable.
    
    	SSD_i_OffsetTemp = SSD_i_Char2send - 32	' Space is now at index 0 all other characters are 32 less into index
    	SSD_i_OffsetTemp = SSD_i_OffsetTemp * 5	' Every character is made of 5 bytes
        for SSD_i_CharIndex=SSD_i_OffsetTemp to SSD_i_OffsetTemp+4
    	IF SSD_i_Char2send < "A" then
    	SSD_i_CharIndexT = SSD_i_CharIndex - 0 	' lookup variable must be 8 bits
        lookup SSD_i_CharIndexT,[$00,$00,$00,$00,$00,$00,$00,$5F,$00,$00,$00,$07,$00,$07,$00,$14,$7F,$14,$7F,$14,_	'sp,!,",#
    					$24,$2A,$7F,$2A,$12,$23,$13,$08,$64,$62,$36,$49,$56,$20,$50,_	'$,%,&
    					$00,$08,$07,$03,$00,$00,$1C,$22,$41,$00,$00,$41,$22,$1C,$00,_	'',(,)
    					$2A,$1C,$7F,$1C,$2A,$08,$08,$3E,$08,$08,$00,$00,$70,$30,$00,_	'*,+,,
    					$08,$08,$08,$08,$08,$00,$00,$60,$60,$00,$20,$10,$08,$04,$02,_	'-,.,/
    					$3E,$51,$49,$45,$3E,$00,$42,$7F,$40,$00,$72,$49,$49,$49,$46,_	'0,1,2
    					$21,$41,$49,$4D,$33,$18,$14,$12,$7F,$10,$27,$45,$45,$45,$39,_	'3,4,5
    					$3C,$4A,$49,$49,$31,$41,$21,$11,$09,$07,$36,$49,$49,$49,$36,_	'6,7,8
    					$46,$49,$49,$29,$1E,$00,$00,$14,$00,$00,$00,$40,$34,$00,$00,_	'9,:,;
    					$00,$08,$14,$22,$41,$14,$14,$14,$14,$14,$00,$41,$22,$14,$08,_	'<,=,>
    					$02,$01,$59,$09,$06,$3E,$41,$5D,$59,$4E],SSD_i_Byte2Send	'?,@
    	elseif  (SSD_i_Char2send < "[") then
    	SSD_i_CharIndexT = SSD_i_CharIndex - 165		' subtract previous table length so "A" = zero
    	lookup SSD_i_CharIndexT,[$7C,$12,$11,$12,$7C,_	'A
    					$7F,$49,$49,$49,$36,$3E,$41,$41,$41,$22,$7F,$41,$41,$41,$3E,_	'B,C,D
    					$7F,$49,$49,$49,$41,$7F,$09,$09,$09,$01,$3E,$41,$41,$51,$73,_	'E,F,G
    					$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$20,$40,$41,$3F,$01,_	'H,I,J
    					$7F,$08,$14,$22,$41,$7F,$40,$40,$40,$40,$7F,$02,$1C,$02,$7F,_	'K,L,M
    					$7F,$04,$08,$10,$7F,$3E,$41,$41,$41,$3E,$7F,$09,$09,$09,$06,_	'N,O,P
    					$3E,$41,$51,$21,$5E,$7F,$09,$19,$29,$46,$26,$49,$49,$49,$32,_	'Q,R,S
    					$03,$01,$7F,$01,$03,$3F,$40,$40,$40,$3F,$1F,$20,$40,$20,$1F,_	'T,U,V
    					$3F,$40,$38,$40,$3F,$63,$14,$08,$14,$63,$03,$04,$78,$04,$03,_	'W,X,Y
    					$61,$59,$49,$4D,$43],SSD_i_Byte2Send	'Z
    	else
    	SSD_i_CharIndexT = SSD_i_CharIndex - 295		' subtract previous tables length so "[" = zero
    	lookup SSD_i_CharIndexT,[$00,$7F,$41,$41,$41,$02,$04,$08,$10,$20,_	'[,\
    					$00,$41,$41,$41,$7F,$04,$02,$01,$02,$04,$40,$40,$40,$40,$40,_	'],^,_
    					$00,$03,$07,$08,$00,$20,$54,$54,$38,$40,$7F,$28,$44,$44,$38,_	'`,a,b
    					$38,$44,$44,$44,$28,$38,$44,$44,$28,$7F,$38,$54,$54,$54,$18,_	'c,d,e
    					$00,$08,$7E,$09,$02,$0C,$52,$52,$4A,$3C,$7F,$08,$04,$04,$78,_	'f,g,h
    					$00,$44,$7D,$40,$00,$20,$40,$40,$3D,$00,$7F,$10,$28,$44,$00,_	'i,j,k
    					$00,$41,$7F,$40,$00,$7C,$04,$78,$04,$78,$7C,$08,$04,$04,$78,_	'l,m,n
    					$38,$44,$44,$44,$38,$7C,$18,$24,$24,$18,$18,$24,$24,$18,$7C,_	'o,p,q
    					$7C,$08,$04,$04,$08,$48,$54,$54,$54,$24,$04,$04,$3F,$44,$24,_	'r,s,t
    					$3C,$40,$40,$20,$7C,$1C,$20,$40,$20,$1C,$3C,$40,$30,$40,$3C,_	'u,v,w
    					$44,$28,$10,$28,$44,$4C,$50,$50,$50,$3C,$44,$64,$54,$4C,$44,_	'x,y,z
    					$00,$08,$36,$41,$00,$00,$00,$77,$00,$00,$00,$41,$36,$08,$00,_	'{,|,}
    					$02,$01,$02,$04,$02],SSD_i_Byte2Send	'~
    	endif
        gosub SSD_i_SendData
        next SSD_i_CharIndex
    	SSD_i_Byte2Send = $00		' space between characters always $00
        gosub SSD_i_SendData
    	return
    '===============================================================================
    SSD1306_i_Around:

  2. #2
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: SSD1306 Include example

    This is a newer version that can use either I2C or SPI. Also a minor improvement to SSD_Clear. Interface handling a little better. Still well under 4K flash. SPI is faster of course. The warnings above about SSD_INIT still apply. This version is using #IFDEF's of V3 so if you are using V2.6 just take out the I2C or SPI code that you don't need.

    Regards
    TimC

    First a Sample of how to use the Include:

    Code:
    'SSD 1306 Sample July 20 2015
    DEFINE OSC 20
    ADCON0=0
    ADCON1=7
    '=======================    Include Configuration    ==========================
    #DEFINE USE_I2C			' Only one Connection allowed  USE_I2C or USE_SPI
    SCL var PortC.3         ' I2C Clock 
    SDA var PortC.4         ' I2C Data 
    '#DEFINE USE_SPI		' Only one Connection allowed  USE_I2C or USE_SPI
    'SSD_DC VAR PORTD.1 	' SPI D/C pin		you will need to set TRIS	
    'SSD_SELECT VAR PORTD.0 ' SPI CS pin		you will need to set TRIS	
    'SSD_RESET var PORTA.1	' SPI Reset pin not used in this code
    'CLOCK VAR PORTC.3 		' SPI Clock
    'MOSI var PORTC.5 		' SPI Data
    Include "SSD1306m.inc"  ' bring it in
    '==========================    MAIN  Routine    ==============================
    temp var byte
    gosub SSD_Init
    looper:
    arraywrite SSD_BUFF,[0,0,"Line 0",0] : gosub SSD_PRINTXY
    arraywrite SSD_BUFF,[" and more",0] : gosub SSD_PRINT	' continue on same line
    arraywrite SSD_BUFF,[30,1,"Middle 1",0] : gosub SSD_PRINTXY
    arraywrite SSD_BUFF,[10,2,"Here we are Line 2",0] : gosub SSD_PRINTXY
    random temp		' jumps about
    arraywrite SSD_BUFF,[0,3,"Current Temp=",dec2 temp, "deg" ,0] : gosub SSD_PRINTXY
    arraywrite SSD_BUFF,[20,5,"Hip Hop Hi Ho 5",0] : gosub SSD_PRINTXY
    arraywrite SSD_BUFF,[10,6,"|%+-./\<=>_     6",0] : gosub SSD_PRINTXY
    arraywrite SSD_BUFF,[10,7,"{}[][email protected]#$%^&*()  7",0] : gosub SSD_PRINTXY
    sleep 1
    GOTO looper
    END
    Now the SSD1306m Include File:

    Code:
    'This Include is for driving a small SSD1306 OLED screen      Version 1.0
    
    'Typical screen is 0.96" 128x64 mono SSD1306 chip with I2C or SPI protocol
    'This code has a large char library in it, so it takes some space, you may
    'delete the top and bottom tables if you need more space for your program but
    'you will need to rewrite the logic and only have Upper case.
    'No bitmap drawing! All text is written directly to the screen to save memory.
    '
    'Screen contains 8 lines (which are 8 pixel height) and 128 columns
    
    ' Setup Instruction: Copy the CONNECTIONS section to your main program
    ' then uncomment and edit the connection you need.  Add the include 
    ' line after the connection:  Include "SSD1306m.inc
    
    ' Typical way to print a formatted line to the DDS1306 Display is like this:
    ' arraywrite SSD_BUFF,[0,3,"Current Temp=",dec2 temp, "deg" ,0] : gosub SSD_PRINTXY
    ' 0= Column in pixels
    ' 3= Row to print on
    ' Last 0 is necessary and to terminate the string to print
    
    ' Public variables and Functions are in the Format SSD_AAAAAA
    ' Private variables and Functions look like SSD_i_AAAAA
    
    '====START  SSD1306  SAMPLE CONNECTIONS ADD THESE TO YOUR MAIN ROUTINE   START=====
    '#DEFINE USE_I2C		' Only one Connection allowed  USE_I2C or USE_SPI
    'SCL var PortC.3        ' I2C Clock  
    'SDA var PortC.4        ' I2C Data   
    '#DEFINE USE_SPI		' Only one Connection allowed  USE_I2C or USE_SPI
    'SSD_DC VAR PORTD.1 	' SPI D/C pin		you will need to set TRIS	
    'SSD_SELECT VAR PORTD.0 ' SPI CS pin		you will need to set TRIS	
    'SSD_RESET var PORTA.1	' SPI Reset pin not used in this code
    'CLOCK VAR PORTC.3 		' SPI Clock
    'MOSI var PORTC.5 		' SPI Data
    '=====END  SSD1306  SAMPLE CONNECTIONS ADD THESE TO YOUR MAIN ROUTINE   END======
    ' Then Include "SSD1306m.inc"  ' bring it in
    '===================  SSD1306  ADDRESS  AND CONSTANTS   ========================
    SSD_i_Device CON $78      ' Normally $78 when using I2C
    SSD_i_DeviceCommand	CON	$00
    SSD_i_DataCommand	CON	$40
    '===================      SSD1306  Messages       ========================
    #IFDEF USE_I2C
    #IFDEF USE_SPI
    	#WARNING "SSD1306 can not use both I2C and SPI interfaces at the same time"
    #ENDIF
    #ENDIF
    '=========================   SSD Variables   ==================================
    SSD_BUFF VAR BYTE[27]	' pass through to Display
    SSD_i_Byte2Send		VAR BYTE	' Prepared byte to be sent to Display
    SSD_i_Byte2Send2	VAR BYTE	' Prepared Byte to be sent to Display
    
    SSD_i_Column VAR BYTE' LCD Column POSITION (0 TO 127)
    SSD_i_Row VAR BYTE'LCD Line POSITION FOR PAGE MODE(0 TO 7)
    
    SSD_i_CharIndex var word 'Char codes index / Loop for clear
    SSD_i_CharIndexT var byte 'char codes index temp
    SSD_i_OffsetTemp var byte	' calculating offset into tables
    
    SSD_i_StringWork var byte 'index for text
    SSD_i_Char2send var byte 'data carrier for text chars
    
    goto SSD1306_i_Around	' this is an add-in so go around
    '====================   SSD1306 initialization   ===============================
    SSD_Init:
    pause 10
    SSD_i_Byte2Send=$AE:GOSUB SSD_i_SendCommand 'Display OFF
    SSD_i_Byte2Send=$D3:SSD_i_Byte2Send2=$00:GOSUB SSD_i_SendCommand2 ' Set offset to 0
    'SSD_i_Byte2Send=$40:GOSUB SSD_i_SendCommand ' Set display start line 0, usually not needed
    SSD_i_Byte2Send=$8D:SSD_i_Byte2Send2=$14:GOSUB SSD_i_SendCommand2 ' Set Charge Pump Internal, usually needed
    SSD_i_Byte2Send=$20:SSD_i_Byte2Send2=$10:GOSUB SSD_i_SendCommand2 ' Adressing mode $10=Page, $00=Horizontal
    SSD_i_Byte2Send=$A1:GOSUB SSD_i_SendCommand	' set segment remap column 127 as start
    SSD_i_Byte2Send=$C8:GOSUB SSD_i_SendCommand ' Com Scan Direction, Flip display vertically
    SSD_i_Byte2Send=$DA:SSD_i_Byte2Send2=$12:GOSUB SSD_i_SendCommand2 ' set COM pins = 128x64=$12   128x32=$02
    SSD_i_Byte2Send=$81:SSD_i_Byte2Send2=$7F:GOSUB SSD_i_SendCommand2 ' Set contrast to $01 to $FF  ($7F is default, $01 is faint)
    SSD_i_Byte2Send=$A4:GOSUB SSD_i_SendCommand ' display ON continue
    SSD_i_Byte2Send=$A6:GOSUB SSD_i_SendCommand ' $A6=NORMAL MODE;  $A7=INVERSE MODE
    SSD_i_Byte2Send=$AF:GOSUB SSD_i_SendCommand 'Display ON
    pause 500	'  look for random bytes. Remove if you would like
    GOSUB SSD_Clear
    return
    '======================Print Lines==============================================
    SSD_Print:
    SSD_i_StringWork = 0	' set index to beginning
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]	' pull letter out of array
    	gosub SSD_i_BuildChar		' Build char and send out
    	SSD_i_StringWork = SSD_i_StringWork + 1		' point to next char
    loop
    return
    
    SSD_PrintXY:
    SSD_i_Column=SSD_BUFF[0]  ' Column in first position
    SSD_i_Row=SSD_BUFF[1]   ' Row in second
    gosub SSD_i_SetXY		' set cursor position
    SSD_i_StringWork = 2			' now point to first character to print
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]
    	gosub SSD_i_BuildChar
    	SSD_i_StringWork = SSD_i_StringWork + 1
    loop
    return
    
    '=====================  Send data  =============================================
    SSD_i_SendData:
    #IFDEF USE_I2C
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,SSD_i_Byte2Send]
    #ELSE
    SSD_DC=1 : SSD_SELECT=0 : pauseus 5		' D/C = High for Data. CS is low to connect
    SHIFTOUT MOSI,CLOCK,1,[SSD_i_Byte2Send]
    #ENDIF
    RETURN
    '====================  Send Command  ===========================================
    SSD_i_SendCommand:
    #IFDEF USE_I2C
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DeviceCommand,SSD_i_Byte2Send]
    #ELSE
    SSD_DC=0 : SSD_SELECT=0 : pauseus 5		' D/C = Low for Commands. CS is low to connect
    SHIFTOUT MOSI,CLOCK,1,[SSD_i_Byte2Send]
    #ENDIF
    RETURN
    '====================  Send Command  ===========================================
    SSD_i_SendCommand2:
    #IFDEF USE_I2C
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DeviceCommand, SSD_i_Byte2Send, SSD_i_Byte2Send2]
    #ELSE
    SSD_DC=0 : SSD_SELECT=0 : pauseus 5		' D/C = Low for Commands. CS is low to connect
    SHIFTOUT MOSI,CLOCK,1,[SSD_i_Byte2Send, SSD_i_Byte2Send2]
    #ENDIF
    RETURN
    '==============================clear lcd========================================
    SSD_Clear:
    #IFDEF USE_I2C
    FOR SSD_i_CharIndex=0 TO 1023
       	I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,$00]	'Send 0 to every column in every line
    NEXT SSD_i_CharIndex
    #ELSE
    SSD_DC=1	' this is data not a command
    FOR SSD_i_CharIndex=0 TO 1023
    	SHIFTOUT MOSI,CLOCK,1,[$00]
    NEXT SSD_i_CharIndex
    #ENDIF
    SSD_i_Column=0 : SSD_i_Row=0 : gosub SSD_i_SetXY	' Go Home
    RETURN
    '===========================================SET X AND Y=========================
    SSD_i_SetXY:
    SSD_i_Byte2Send=$21:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Column:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=127:GOSUB SSD_i_SendCommand
    'Above 3 lines means; Column starts at SSD_i_Column and End at 127
    SSD_i_Byte2Send=$22:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Row:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Row:GOSUB SSD_i_SendCommand
    'Above 3 lines means; Line starts at SSD_i_Row and end at SSD_i_Row,
    'which means ; Only work on specified line!
    RETURN
    '=============================Find Char  2=======================================
    SSD_i_BuildChar:
    ' Enter this Subroutine with printable character: SSD_i_Char2send
    ' SSD_i_Char2send is subtracted from " " (space char) and * by 5 to be able to index into one table
    ' One table is broken into 3 to avoid the 255 max.  Index into table must be a byte variable.
    
    	SSD_i_OffsetTemp = SSD_i_Char2send - 32	' Space is now at index 0 all other characters are 32 less into index
    	SSD_i_OffsetTemp = SSD_i_OffsetTemp * 5	' Every character is made of 5 bytes
        for SSD_i_CharIndex=SSD_i_OffsetTemp to SSD_i_OffsetTemp+4
    	IF SSD_i_Char2send < "A" then
    	SSD_i_CharIndexT = SSD_i_CharIndex - 0 	' lookup variable must be 8 bits
        lookup SSD_i_CharIndexT,[$00,$00,$00,$00,$00,$00,$00,$5F,$00,$00,$00,$07,$00,$07,$00,$14,$7F,$14,$7F,$14,_	'sp,!,",#
    					$24,$2A,$7F,$2A,$12,$23,$13,$08,$64,$62,$36,$49,$56,$20,$50,_	'$,%,&
    					$00,$08,$07,$03,$00,$00,$1C,$22,$41,$00,$00,$41,$22,$1C,$00,_	'',(,)
    					$2A,$1C,$7F,$1C,$2A,$08,$08,$3E,$08,$08,$00,$00,$70,$30,$00,_	'*,+,,
    					$08,$08,$08,$08,$08,$00,$00,$60,$60,$00,$20,$10,$08,$04,$02,_	'-,.,/
    					$3E,$51,$49,$45,$3E,$00,$42,$7F,$40,$00,$72,$49,$49,$49,$46,_	'0,1,2
    					$21,$41,$49,$4D,$33,$18,$14,$12,$7F,$10,$27,$45,$45,$45,$39,_	'3,4,5
    					$3C,$4A,$49,$49,$31,$41,$21,$11,$09,$07,$36,$49,$49,$49,$36,_	'6,7,8
    					$46,$49,$49,$29,$1E,$00,$00,$14,$00,$00,$00,$40,$34,$00,$00,_	'9,:,;
    					$00,$08,$14,$22,$41,$14,$14,$14,$14,$14,$00,$41,$22,$14,$08,_	'<,=,>
    					$02,$01,$59,$09,$06,$3E,$41,$5D,$59,$4E],SSD_i_Byte2Send	'?,@
    	elseif  (SSD_i_Char2send < "[") then
    	SSD_i_CharIndexT = SSD_i_CharIndex - 165		' subtract previous table length so "A" = zero
    	lookup SSD_i_CharIndexT,[$7C,$12,$11,$12,$7C,_	'A
    					$7F,$49,$49,$49,$36,$3E,$41,$41,$41,$22,$7F,$41,$41,$41,$3E,_	'B,C,D
    					$7F,$49,$49,$49,$41,$7F,$09,$09,$09,$01,$3E,$41,$41,$51,$73,_	'E,F,G
    					$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$20,$40,$41,$3F,$01,_	'H,I,J
    					$7F,$08,$14,$22,$41,$7F,$40,$40,$40,$40,$7F,$02,$1C,$02,$7F,_	'K,L,M
    					$7F,$04,$08,$10,$7F,$3E,$41,$41,$41,$3E,$7F,$09,$09,$09,$06,_	'N,O,P
    					$3E,$41,$51,$21,$5E,$7F,$09,$19,$29,$46,$26,$49,$49,$49,$32,_	'Q,R,S
    					$03,$01,$7F,$01,$03,$3F,$40,$40,$40,$3F,$1F,$20,$40,$20,$1F,_	'T,U,V
    					$3F,$40,$38,$40,$3F,$63,$14,$08,$14,$63,$03,$04,$78,$04,$03,_	'W,X,Y
    					$61,$59,$49,$4D,$43],SSD_i_Byte2Send	'Z
    	else
    	SSD_i_CharIndexT = SSD_i_CharIndex - 295		' subtract previous tables length so "[" = zero
    	lookup SSD_i_CharIndexT,[$00,$7F,$41,$41,$41,$02,$04,$08,$10,$20,_	'[,\
    					$00,$41,$41,$41,$7F,$04,$02,$01,$02,$04,$40,$40,$40,$40,$40,_	'],^,_
    					$00,$03,$07,$08,$00,$20,$54,$54,$38,$40,$7F,$28,$44,$44,$38,_	'`,a,b
    					$38,$44,$44,$44,$28,$38,$44,$44,$28,$7F,$38,$54,$54,$54,$18,_	'c,d,e
    					$00,$08,$7E,$09,$02,$0C,$52,$52,$4A,$3C,$7F,$08,$04,$04,$78,_	'f,g,h
    					$00,$44,$7D,$40,$00,$20,$40,$40,$3D,$00,$7F,$10,$28,$44,$00,_	'i,j,k
    					$00,$41,$7F,$40,$00,$7C,$04,$78,$04,$78,$7C,$08,$04,$04,$78,_	'l,m,n
    					$38,$44,$44,$44,$38,$7C,$18,$24,$24,$18,$18,$24,$24,$18,$7C,_	'o,p,q
    					$7C,$08,$04,$04,$08,$48,$54,$54,$54,$24,$04,$04,$3F,$44,$24,_	'r,s,t
    					$3C,$40,$40,$20,$7C,$1C,$20,$40,$20,$1C,$3C,$40,$30,$40,$3C,_	'u,v,w
    					$44,$28,$10,$28,$44,$4C,$50,$50,$50,$3C,$44,$64,$54,$4C,$44,_	'x,y,z
    					$00,$08,$36,$41,$00,$00,$00,$77,$00,$00,$00,$41,$36,$08,$00,_	'{,|,}
    					$02,$01,$02,$04,$02],SSD_i_Byte2Send	'~
    	endif
        gosub SSD_i_SendData
        next SSD_i_CharIndex
    	SSD_i_Byte2Send = $00		' space between characters always $00
        gosub SSD_i_SendData
    	return
    '===============================================================================
    SSD1306_i_Around:

  3. #3
    Join Date
    Apr 2013
    Posts
    32

    Default Re: SSD1306 Include example

    Hello TimC,
    I was trying to create a second char table with your include file which is double sized fonts. I used page mode and double lines to create fonts (maybe using horizontal mode was better but I believe that the best way is the way you know).
    So I modified your include file a bit. But the thing is I wasn't able to understand your table logic so I couldn't create a table like yours and so I added my table style for bigger fonts.
    Since my char codes take much place, I only added numbers here, if you could explain or show me how to convert these to table like yours that would be great
    I want to explain changes I made first;
    To use big fonts, arraywrite SSD_BUFF,[column,row,"string" or decx number or variable,0] : gosub SSD_PRINTXY_Big

    I created and divided fonts from half, upper side first row, lower side next row, SSD_PRINTXY_Big takes SSD_BUFF contents and prints upper half to first row and then goes back of SSD_BUFF and again prins lower half of chars to next row.
    It is working as it is but need some more improvement =)
    Here is your modified inc file
    Code:
    '===================  SSD1306  ADDRESS  AND CONSTANTS   ========================
    SSD_i_Device CON $78      ' Normally $78 when using I2C
    SSD_i_DeviceCommand	CON	$00
    SSD_i_DataCommand	CON	$40
    '===================      SSD1306  Messages       ========================
    #IFDEF USE_I2C
    #IFDEF USE_SPI
    	#WARNING "SSD1306 can not use both I2C and SPI interfaces at the same time"
    #ENDIF
    #ENDIF
    '=========================   SSD Variables   ==================================
    SSD_BUFF VAR BYTE[27]	' pass through to Display
    SSD_i_Byte2Send		VAR BYTE	' Prepared byte to be sent to Display
    SSD_i_Byte2Send2	VAR BYTE	' Prepared Byte to be sent to Display
    
    SSD_i_Column VAR BYTE' LCD Column POSITION (0 TO 127)
    SSD_i_Row VAR BYTE'LCD Line POSITION FOR PAGE MODE(0 TO 7)
    
    SSD_i_CharIndex var word 'Char codes index / Loop for clear
    SSD_i_CharIndexT var byte 'char codes index temp
    SSD_i_OffsetTemp var byte	' calculating offset into tables
    
    SSD_i_StringWork var byte 'index for text
    SSD_i_Char2send var byte 'data carrier for text chars
    
    goto SSD1306_i_Around	' this is an add-in so go around
    '====================   SSD1306 initialization   ===============================
    SSD_Init:
    pause 10
    SSD_i_Byte2Send=$AE:GOSUB SSD_i_SendCommand 'Display OFF
    SSD_i_Byte2Send=$D3:SSD_i_Byte2Send2=$00:GOSUB SSD_i_SendCommand2 ' Set offset to 0
    'SSD_i_Byte2Send=$40:GOSUB SSD_i_SendCommand ' Set display start line 0, usually not needed
    SSD_i_Byte2Send=$8D:SSD_i_Byte2Send2=$14:GOSUB SSD_i_SendCommand2 ' Set Charge Pump Internal, usually needed
    SSD_i_Byte2Send=$20:SSD_i_Byte2Send2=$10:GOSUB SSD_i_SendCommand2 ' Adressing mode $10=Page, $00=Horizontal
    SSD_i_Byte2Send=$A1:GOSUB SSD_i_SendCommand	' set segment remap column 127 as start
    SSD_i_Byte2Send=$C8:GOSUB SSD_i_SendCommand ' Com Scan Direction, Flip display vertically
    SSD_i_Byte2Send=$DA:SSD_i_Byte2Send2=$12:GOSUB SSD_i_SendCommand2 ' set COM pins = 128x64=$12   128x32=$02
    SSD_i_Byte2Send=$81:SSD_i_Byte2Send2=$7F:GOSUB SSD_i_SendCommand2 ' Set contrast to $01 to $FF  ($7F is default, $01 is faint)
    SSD_i_Byte2Send=$A4:GOSUB SSD_i_SendCommand ' display ON continue
    SSD_i_Byte2Send=$A6:GOSUB SSD_i_SendCommand ' $A6=NORMAL MODE;  $A7=INVERSE MODE
    SSD_i_Byte2Send=$AF:GOSUB SSD_i_SendCommand 'Display ON
    pause 500	'  look for random bytes. Remove if you would like
    GOSUB SSD_Clear
    return
    '======================Print Lines==============================================
    SSD_Print:
    SSD_i_StringWork = 0	' set index to beginning
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]	' pull letter out of array
    	gosub SSD_i_BuildChar		' Build char and send out
    	SSD_i_StringWork = SSD_i_StringWork + 1		' point to next char
    loop
    return
    
    SSD_PrintXY:
    SSD_i_Column=SSD_BUFF[0]  ' Column in first position
    SSD_i_Row=SSD_BUFF[1]   ' Row in second
    gosub SSD_i_SetXY		' set cursor position
    SSD_i_StringWork = 2			' now point to first character to print
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]
    	gosub SSD_i_BuildChar
    	SSD_i_StringWork = SSD_i_StringWork + 1
    loop
    return
    
    SSD_PrintXY_Big:
    SSD_i_Column=SSD_BUFF[0]  ' Column in first position
    SSD_i_Row=SSD_BUFF[1]   ' Row in second
    gosub SSD_i_SetXY		' set cursor position
    SSD_i_StringWork = 2			' now point to first character to print
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]
    	for SSD_i_CharIndex=0 to 10
    	gosub SSD_i_Big_Char_up
    	next SSD_i_CharIndex
    	SSD_i_Byte2Send=$00 : gosub SSD_i_SendData
    	SSD_i_StringWork = SSD_i_StringWork + 1
    loop
    SSD_i_StringWork = 2
    SSD_i_Row=SSD_i_Row+1
    SSD_i_Column=SSD_BUFF[0]  ' Column in first position
    gosub SSD_i_SetXY
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]
    	for SSD_i_CharIndex=0 to 10
    	gosub SSD_i_Big_Char_Down
    	next SSD_i_CharIndex
    	SSD_i_Byte2Send=$00 : gosub SSD_i_SendData
    	SSD_i_StringWork = SSD_i_StringWork + 1
    loop
    return
    
    '=====================  Send data  =============================================
    SSD_i_SendData:
    #IFDEF USE_I2C
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,SSD_i_Byte2Send]
    '#ELSE
    'SSD_DC=1 : SSD_SELECT=0 : pauseus 5		' D/C = High for Data. CS is low to connect
    'SHIFTOUT MOSI,CLOCK,1,[SSD_i_Byte2Send]
    #ENDIF
    RETURN
    '====================  Send Command  ===========================================
    SSD_i_SendCommand:
    #IFDEF USE_I2C
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DeviceCommand,SSD_i_Byte2Send]
    '#ELSE
    'SSD_DC=0 : SSD_SELECT=0 : pauseus 5		' D/C = Low for Commands. CS is low to connect
    'SHIFTOUT MOSI,CLOCK,1,[SSD_i_Byte2Send]
    #ENDIF
    RETURN
    '====================  Send Command  ===========================================
    SSD_i_SendCommand2:
    #IFDEF USE_I2C
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DeviceCommand, SSD_i_Byte2Send, SSD_i_Byte2Send2]
    '#ELSE
    'SSD_DC=0 : SSD_SELECT=0 : pauseus 5		' D/C = Low for Commands. CS is low to connect
    'SHIFTOUT MOSI,CLOCK,1,[SSD_i_Byte2Send, SSD_i_Byte2Send2]
    #ENDIF
    RETURN
    '==============================clear lcd========================================
    SSD_Clear:
    #IFDEF USE_I2C
    SSD_i_Column=0
    for SSD_i_Row=0 to 7
    gosub SSD_i_SetXY
    FOR SSD_i_CharIndex=0 TO 127
       	I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,$00]	'Send 0 to every column in every line
    NEXT SSD_i_CharIndex
    next SSD_i_Row
    '#ELSE
    'SSD_DC=1	' this is data not a command
    'FOR SSD_i_CharIndex=0 TO 1023
    '	SHIFTOUT MOSI,CLOCK,1,[$00]
    'NEXT SSD_i_CharIndex
    #ENDIF
    SSD_i_Column=0 : SSD_i_Row=0 : gosub SSD_i_SetXY	' Go Home
    RETURN
    
    '===========================================SET X AND Y=========================
    SSD_i_SetXY:
    SSD_i_Byte2Send=$21:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Column:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=127:GOSUB SSD_i_SendCommand
    'Above 3 lines means; Column starts at SSD_i_Column and End at 127
    SSD_i_Byte2Send=$22:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Row:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Row:GOSUB SSD_i_SendCommand
    'Above 3 lines means; Line starts at SSD_i_Row and end at SSD_i_Row,
    'which means ; Only work on specified line!
    RETURN
    '=============================Find Char  2=======================================
    SSD_i_BuildChar:
    ' Enter this Subroutine with printable character: SSD_i_Char2send
    ' SSD_i_Char2send is subtracted from " " (space char) and * by 5 to be able to index into one table
    ' One table is broken into 3 to avoid the 255 max.  Index into table must be a byte variable.
    
    	SSD_i_OffsetTemp = SSD_i_Char2send - 32	' Space is now at index 0 all other characters are 32 less into index
    	SSD_i_OffsetTemp = SSD_i_OffsetTemp * 5	' Every character is made of 5 bytes
        for SSD_i_CharIndex=SSD_i_OffsetTemp to SSD_i_OffsetTemp+4
    	IF SSD_i_Char2send < "A" then
    	SSD_i_CharIndexT = SSD_i_CharIndex - 0 	' lookup variable must be 8 bits
        lookup SSD_i_CharIndexT,[$00,$00,$00,$00,$00,$00,$00,$5F,$00,$00,$00,$07,$00,$07,$00,$14,$7F,$14,$7F,$14,_	'sp,!,",#
    					$24,$2A,$7F,$2A,$12,$23,$13,$08,$64,$62,$36,$49,$56,$20,$50,_	'$,%,&
    					$00,$08,$07,$03,$00,$00,$1C,$22,$41,$00,$00,$41,$22,$1C,$00,_	'',(,)
    					$2A,$1C,$7F,$1C,$2A,$08,$08,$3E,$08,$08,$00,$00,$70,$30,$00,_	'*,+,,
    					$08,$08,$08,$08,$08,$00,$00,$60,$60,$00,$20,$10,$08,$04,$02,_	'-,.,/
    					$3E,$51,$49,$45,$3E,$00,$42,$7F,$40,$00,$72,$49,$49,$49,$46,_	'0,1,2
    					$21,$41,$49,$4D,$33,$18,$14,$12,$7F,$10,$27,$45,$45,$45,$39,_	'3,4,5
    					$3C,$4A,$49,$49,$31,$41,$21,$11,$09,$07,$36,$49,$49,$49,$36,_	'6,7,8
    					$46,$49,$49,$29,$1E,$00,$00,$14,$00,$00,$00,$40,$34,$00,$00,_	'9,:,;
    					$00,$08,$14,$22,$41,$14,$14,$14,$14,$14,$00,$41,$22,$14,$08,_	'<,=,>
    					$02,$01,$59,$09,$06,$3E,$41,$5D,$59,$4E],SSD_i_Byte2Send	'?,@
    	elseif  (SSD_i_Char2send < "[") then
    	SSD_i_CharIndexT = SSD_i_CharIndex - 165		' subtract previous table length so "A" = zero
    	lookup SSD_i_CharIndexT,[$7C,$12,$11,$12,$7C,_	'A
    					$7F,$49,$49,$49,$36,$3E,$41,$41,$41,$22,$7F,$41,$41,$41,$3E,_	'B,C,D
    					$7F,$49,$49,$49,$41,$7F,$09,$09,$09,$01,$3E,$41,$41,$51,$73,_	'E,F,G
    					$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$20,$40,$41,$3F,$01,_	'H,I,J
    					$7F,$08,$14,$22,$41,$7F,$40,$40,$40,$40,$7F,$02,$1C,$02,$7F,_	'K,L,M
    					$7F,$04,$08,$10,$7F,$3E,$41,$41,$41,$3E,$7F,$09,$09,$09,$06,_	'N,O,P
    					$3E,$41,$51,$21,$5E,$7F,$09,$19,$29,$46,$26,$49,$49,$49,$32,_	'Q,R,S
    					$03,$01,$7F,$01,$03,$3F,$40,$40,$40,$3F,$1F,$20,$40,$20,$1F,_	'T,U,V
    					$3F,$40,$38,$40,$3F,$63,$14,$08,$14,$63,$03,$04,$78,$04,$03,_	'W,X,Y
    					$61,$59,$49,$4D,$43],SSD_i_Byte2Send	'Z
    	else
    	SSD_i_CharIndexT = SSD_i_CharIndex - 295		' subtract previous tables length so "[" = zero
    	lookup SSD_i_CharIndexT,[$00,$7F,$41,$41,$41,$02,$04,$08,$10,$20,_	'[,\
    					$00,$41,$41,$41,$7F,$04,$02,$01,$02,$04,$40,$40,$40,$40,$40,_	'],^,_
    					$00,$03,$07,$08,$00,$20,$54,$54,$38,$40,$7F,$28,$44,$44,$38,_	'`,a,b
    					$38,$44,$44,$44,$28,$38,$44,$44,$28,$7F,$38,$54,$54,$54,$18,_	'c,d,e
    					$00,$08,$7E,$09,$02,$0C,$52,$52,$4A,$3C,$7F,$08,$04,$04,$78,_	'f,g,h
    					$00,$44,$7D,$40,$00,$20,$40,$40,$3D,$00,$7F,$10,$28,$44,$00,_	'i,j,k
    					$00,$41,$7F,$40,$00,$7C,$04,$78,$04,$78,$7C,$08,$04,$04,$78,_	'l,m,n
    					$38,$44,$44,$44,$38,$7C,$18,$24,$24,$18,$18,$24,$24,$18,$7C,_	'o,p,q
    					$7C,$08,$04,$04,$08,$48,$54,$54,$54,$24,$04,$04,$3F,$44,$24,_	'r,s,t
    					$3C,$40,$40,$20,$7C,$1C,$20,$40,$20,$1C,$3C,$40,$30,$40,$3C,_	'u,v,w
    					$44,$28,$10,$28,$44,$4C,$50,$50,$50,$3C,$44,$64,$54,$4C,$44,_	'x,y,z
    					$00,$08,$36,$41,$00,$00,$00,$77,$00,$00,$00,$41,$36,$08,$00,_	'{,|,}
    					$02,$01,$02,$04,$02],SSD_i_Byte2Send	'~
    	endif
        gosub SSD_i_SendData
        next SSD_i_CharIndex
    	SSD_i_Byte2Send = $00		' space between characters always $00
        gosub SSD_i_SendData
    	return
    '===============================================================================
    '=============================Big Numbers=======================================
    SSD_i_Big_Char_Up:
    select case SSD_i_Char2send
    case "0",0
        lookup SSD_i_CharIndex,[$07,$0F,$18,$30,$60,$60,$60,$30,$18,$0F,$07],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "1",1
      	lookup SSD_i_CharIndex,[$00,$00,$18,$30,$60,$7F,$7F,$00,$00,$00,$00],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "2",2
      	lookup SSD_i_CharIndex,[$00,$0C,$1C,$30,$60,$60,$60,$61,$33,$1E,$0C],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "3",3
      	lookup SSD_i_CharIndex,[$18,$30,$60,$60,$61,$61,$61,$33,$1E,$0C,$00],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "4",4
      	lookup SSD_i_CharIndex,[$00,$00,$01,$03,$06,$0C,$18,$3F,$7F,$00,$00],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "5",5
      	lookup SSD_i_CharIndex,[$7F,$7F,$63,$63,$63,$63,$63,$63,$61,$60,$60],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "6",6
      	lookup SSD_i_CharIndex,[$0F,$1F,$30,$60,$60,$60,$60,$60,$60,$30,$10],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "7",7
      	lookup SSD_i_CharIndex,[$78,$78,$60,$60,$60,$60,$60,$63,$6F,$7C,$70],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "8",8
      	lookup SSD_i_CharIndex,[$1E,$3F,$61,$61,$61,$61,$61,$61,$61,$3F,$1E],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "9",9
      	lookup SSD_i_CharIndex,[$1E,$3F,$61,$61,$61,$61,$61,$61,$61,$3F,$1F],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    end select
    return
    
    
    SSD_i_Big_Char_Down:
    
    
    select case SSD_i_Char2send
    case "0",0
        lookup SSD_i_CharIndex,[$F0,$F8,$0C,$06,$03,$03,$03,$06,$0C,$F8,$F0],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "1",1
      	lookup SSD_i_CharIndex,[$00,$00,$03,$03,$03,$FF,$FF,$03,$03,$03,$00],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "2",2
      	lookup SSD_i_CharIndex,[$03,$07,$0F,$1B,$33,$63,$C3,$83,$03,$03,$03],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "3",3
      	lookup SSD_i_CharIndex,[$0C,$06,$03,$03,$83,$83,$83,$86,$FC,$78,$00],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "4",4
      	lookup SSD_i_CharIndex,[$78,$D8,$98,$18,$18,$18,$18,$FF,$FF,$18,$18],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "5",5
      	lookup SSD_i_CharIndex,[$04,$06,$03,$03,$03,$03,$03,$03,$86,$FC,$78],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "6",6
      	lookup SSD_i_CharIndex,[$FC,$FE,$C3,$C3,$C3,$C3,$C3,$C3,$C3,$7E,$3C],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "7",7
      	lookup SSD_i_CharIndex,[$00,$00,$00,$03,$0F,$3C,$F0,$C0,$00,$00,$00],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "8",8
      	lookup SSD_i_CharIndex,[$3C,$7E,$C3,$83,$83,$83,$83,$83,$C3,$7E,$3C],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    case "9",9
      	lookup SSD_i_CharIndex,[$04,$06,$83,$83,$83,$83,$83,$83,$86,$FC,$F8],SSD_i_Byte2Send
      	SSD_i_Byte2Send=SSD_i_Byte2Send rev 8 : gosub SSD_i_SendData : return
    end select
    return
    '===============================================================================
    
    SSD1306_i_Around:

  4. #4
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: SSD1306 Include example

    If you want Larger fonts one approach would be to use the same tables and work from the pixel level. Just make every pixel multiple times the size. The characters do look boxy but easy to read. Here is a start from "C" code:

    Code:
             FOR j = 0 to 4 step size 'Loop through character byte data
                FOR  k = 0 to 6*size  ' Loop through the vertical pixels
                   IF pixelData[j] = 1  then  ' k=1 'Check if the pixel should be set  <== not correct in PBP
                      FOR  l = 0 to size  'The next two loops change the character's size
                        FOR m = 0 to size 
                            OLED_pixel  x + m, y+k * size + l   'Draws the pixel at x, y
                        Next m
                      Next l
                   end if
                Next k
             Next J
    I hope this gives you a start.

  5. #5
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: SSD1306 Include example

    I was able to get the Double size text to work. Also lines. Still fits in 4K but I had to give up PIC16's because of the 256 byte restriction on the lookup table.

    Tested the code on more displays both .96 and 1.3". The SH1106 works as well. There are now 2 types of Clear and Go to XY. If one does not work try the other.

    Making a Box takes some work since joining the corners is not that easy.
    I'm sending a Pic on the next post.

    Enjoy

    TimC

    Code:
    'SSD 1306 Sample Aug 7 2015
    DEFINE OSC 20
    ADCON0=0
    ADCON1=7
    '=======================    Include Configuration    ==========================
    '#DEFINE USE_I2C			' Only one Connection allowed  USE_I2C or USE_SPI
    SCL var PortC.3         ' I2C Clock
    SDA var PortC.4         ' I2C Data
    #DEFINE USE_SPI		' Only one Connection allowed  USE_I2C or USE_SPI
    SSD_DC VAR PORTD.1 	' SPI D/C pin		you will need to set TRIS
    TRISD.1 = 0
    #DEFINE USE_SPI_SELECT	' activates select code
    SSD_SELECT VAR PORTD.0 ' SPI CS pin		you will need to set TRIS also
    TRISD.0 = 0
    #DEFINE USE_SPI_RESET	' activates reset code
    SSD_RESET var PORTD.0	' SPI Reset pin  was A.1
    TRISD.0 = 0
    CLOCK VAR PORTC.3 		' SPI Clock
    MOSI var PORTC.5 		' SPI Data
    Include "N:\PIC\PicBasicPro\include\LABx1.inc"  ' set all the pin names
    Include "N:\PIC\PicBasicPro\include\SSD1306m.inc"  ' bring it in
    '==========================    MAIN  Routine    ==============================
    temper var byte
    gosub SSD_Init
    looper:
    pause 500
    
    arraywrite SSD_BUFF,[0,0,"Nice + Big",0] : gosub SSD_PrintXYDouble
    arraywrite SSD_BUFF,[25,2,"No it's .96",0] : gosub SSD_PRINTXY
    
    arraywrite SSD_BUFF,[0,4,125,$0F] : gosub SSD_PRINThLine 'colstart,row,length,pattern			Big fat line
    
    arraywrite SSD_BUFF,[100,5,20,$08] : gosub SSD_PRINThLine 'colstart,row,length,pattern			top of Box
    arraywrite SSD_BUFF,[100,7,20,$08] : gosub SSD_PRINThLine 'colstart,row,length,pattern          bottom
    arraywrite SSD_BUFF,[100,5,5,17] : gosub SSD_PRINTvLine 'col,row,Starting Height,total length	Left Side
    arraywrite SSD_BUFF,[120,5,5,17] : gosub SSD_PRINTvLine 'col,row,Starting Height,total length	Right Side
    random temper		' jumps about
    arraywrite SSD_BUFF,[10,6,"Current Temp =",0] : gosub SSD_PRINTXY								'label
    arraywrite SSD_BUFF,[105,6,dec2 temper,0] : gosub SSD_PRINTXY									'value in box
    
    sleep 1
    GOTO looper
    
    END
    Code:
    'This Include is for driving a small SSD1306/SH1106 OLED screen      Version 1.1
    
    'Typical screen is 0.96" 128x64 mono SSD1306 chip with I2C or SPI protocol
    'Also tested with SH1106 chip and 1.3" screens
    'This code has a large char library in it, so it takes some space  
    'Because of the large table this addin requires a PIC18
    'No bitmap drawing! All text is written directly to the screen to save memory.
    'There is Vert and Horiz lines if needed as well as Double size characters
    '
    'Screen contains 8 lines (which are 8 pixel height) and 128 columns
    
    ' Setup Instruction: Copy the CONNECTIONS section to your main program
    ' then uncomment and edit the connection you need.  Add the include 
    ' line after the connection:  Include "SSD1306m.inc
    
    ' Typical way to print a formatted line to the DDS1306 Display is like this:
    ' arraywrite SSD_BUFF,[0,3,"Current Temp=",dec2 temp, "deg" ,0] : gosub SSD_PRINTXY
    ' 0= Column in pixels
    ' 3= Row to print on
    ' Last 0 is necessary and to terminate the string to print
    
    ' Public variables and Functions are in the Format SSD_AAAAAA
    ' Private variables and Functions look like SSD_i_AAAAA
    
    '====START  SSD1306  SAMPLE CONNECTIONS ADD THESE TO YOUR MAIN ROUTINE   START=====
    '#DEFINE USE_I2C		' Only one Connection allowed  USE_I2C or USE_SPI
    'SCL var PortC.3        ' I2C Clock  
    'SDA var PortC.4        ' I2C Data   
    '#DEFINE USE_SPI		' Only one Connection allowed  USE_I2C or USE_SPI
    'SSD_DC VAR PORTD.1 	' SPI D/C pin		you will need to set TRIS	
    'SSD_SELECT VAR PORTD.0 ' SPI CS pin		you will need to set TRIS	
    'SSD_RESET var PORTA.1	' SPI Reset pin not used in this code
    'CLOCK VAR PORTC.3 		' SPI Clock
    'MOSI var PORTC.5 		' SPI Data
    '=====END  SSD1306  SAMPLE CONNECTIONS ADD THESE TO YOUR MAIN ROUTINE   END======
    ' Then Include "SSD1306m.inc"  ' bring it in
    '===================  SSD1306  ADDRESS  AND CONSTANTS   ========================
    SSD_i_Device CON $78      ' Normally $78 when using I2C
    SSD_i_DeviceCommand	CON	$00
    SSD_i_DataCommand	CON	$40
    '===================      SSD1306  Messages       ========================
    #IFDEF USE_I2C
    #IFDEF USE_SPI
    	#WARNING "SSD1306 can not use both I2C and SPI interfaces at the same time"
    #ENDIF
    #ENDIF
    '=========================   SSD Variables   ==================================
    SSD_BUFF VAR BYTE[27]	' pass through to Display
    SSD_i_DBuffInput var byte[6]	' Holding the double size character
    SSD_i_DBuffOutput var word	' Holding one column of the double size character
    SSD_i_Byte2Send		VAR BYTE	' Prepared byte to be sent to Display
    SSD_i_Byte2Send2	VAR BYTE	' Prepared Byte to be sent to Display
    
    SSD_i_Column VAR BYTE' LCD Column POSITION (0 TO 127 or 132 for SH1106)
    SSD_i_Row VAR BYTE'LCD Line POSITION FOR PAGE MODE(0 TO 7)
    'SSD_i_Page VAR BYTE'LCD Line POSITION FOR PAGE MODE(0 TO 7)
    
    
    SSD_i_CharIndex var word 'Char codes index / Loop for clear
    SSD_i_CharIndexT var byte 'char codes index temp
    SSD_i_OffsetTemp var word	' calculating offset into tables
    SSD_i_BitOffsetTemp var byte	' calculating bit offset in bytes
    
    SSD_i_StringWork var byte 'index for text
    SSD_i_Char2send var byte 'data carrier for text chars
    
    goto SSD1306_i_Around	' this is an add-in so go around
    '====================   SSD1306 initialization   ===============================
    SSD_Init:
    #IFDEF USE_SPI_RESET
    SSD_RESET = 0 : pause 1 : SSD_RESET = 1
    #ENDIF
    pause 10
    SSD_i_Byte2Send=$AE:GOSUB SSD_i_SendCommand 'Display OFF
    'SSD_i_Byte2Send=$D3:SSD_i_Byte2Send2=$00:GOSUB SSD_i_SendCommand2 ' Set Display Offset Mode Set 0  [PUD=$00]
    'SSD_i_Byte2Send=$40:GOSUB SSD_i_SendCommand ' Set display start line 0 [PUD=$40], usually not needed
    SSD_i_Byte2Send=$8D:SSD_i_Byte2Send2=$14:GOSUB SSD_i_SendCommand2 ' Set Charge Pump Internal, usually needed
    SSD_i_Byte2Send=$20:SSD_i_Byte2Send2=$10:GOSUB SSD_i_SendCommand2 ' Adressing mode $10=Page, $00=Horizontal
    'SSD_i_Byte2Send=$B0:GOSUB SSD_i_SendCommand ' Set Page Address From $B0 to $B7 [PUD=$B0], usally not needed 
    SSD_i_Byte2Send=$A1:GOSUB SSD_i_SendCommand	' set segment remap column 127 as start
    'SSD_i_Byte2Send=$A8:SSD_i_Byte2Send2=$3F:GOSUB SSD_i_SendCommand2 ' Set Multiplex Ration from $00 to $3F, usually not needed
    SSD_i_Byte2Send=$C8:GOSUB SSD_i_SendCommand ' Com Scan Direction, Flip display vertically
    SSD_i_Byte2Send=$DA:SSD_i_Byte2Send2=$12:GOSUB SSD_i_SendCommand2 ' set COM pins = 128x64=$12   128x32=$02
    'SSD_i_Byte2Send=$81:SSD_i_Byte2Send2=$7F:GOSUB SSD_i_SendCommand2 ' Set contrast to $01 to $FF  ($7F is default, $01 is faint)
    'SSD_i_Byte2Send=$D5:SSD_i_Byte2Send2=$F0:GOSUB SSD_i_SendCommand2 ' Set Display Clock / Ratio, Optional
    'SSD_i_Byte2Send=$9D:SSD_i_Byte2Send2=$22:GOSUB SSD_i_SendCommand2 ' Set Dis-Charge Pre-Charge Period, Optional
    'SSD_i_Byte2Send=$DB:SSD_i_Byte2Send2=$20:GOSUB SSD_i_SendCommand2 ' Set VCOM Deselect Level, Optional
    SSD_i_Byte2Send=$A4:GOSUB SSD_i_SendCommand ' display ON continue
    SSD_i_Byte2Send=$A6:GOSUB SSD_i_SendCommand ' $A6=NORMAL MODE;  $A7=INVERSE MODE
    SSD_i_Byte2Send=$AF:GOSUB SSD_i_SendCommand 'Display ON
    pause 500	'  look for random bytes. Remove if you would like
    GOSUB SSD_Clear2
    return
    '======================Print Lines==============================================
    SSD_Print:
    SSD_i_StringWork = 0	' set index to beginning
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]	' pull letter out of array
    	gosub SSD_i_BuildChar		' Build 5 byte char array
    	gosub SSD_i_SendChar		' Read Array and send it out 
    	SSD_i_StringWork = SSD_i_StringWork + 1		' point to next char
    loop
    return
    
    SSD_PrintXY:
    SSD_i_Column=SSD_BUFF[0]  ' Column in first position
    SSD_i_Row=SSD_BUFF[1]   ' Row in second
    gosub SSD_i_SetXY2		' set cursor position
    SSD_i_StringWork = 2			' now point to first character to print
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]
    	gosub SSD_i_BuildChar		' Build 5 byte char array
    	gosub SSD_i_SendChar		' Read Array and send it out 
    	SSD_i_StringWork = SSD_i_StringWork + 1
    loop
    return
    
    SSD_PrintXYDouble:
    SSD_i_Column=SSD_BUFF[0]  ' Column in first position
    SSD_i_Row=SSD_BUFF[1]   ' Row in second
    gosub SSD_i_SetXY2		' set cursor position
    SSD_i_StringWork = 2			' now point to first character to print
    DO while SSD_BUFF[SSD_i_StringWork] <> 0
    	SSD_i_Char2send = SSD_BUFF[SSD_i_StringWork]
    	gosub SSD_i_BuildChar		' Get the large table data
    	gosub SSD_i_MakeDoubleChar	' Double it and print it
    	SSD_i_StringWork = SSD_i_StringWork + 1
    loop
    return
    '=====================  Send Double Char  ======================================
    SSD_i_MakeDoubleChar
    ' This subroutine is run after BuildChar.  SSD_i_DBuffInput must be loaded
    ' SSD_i_DBuffInput is used to load SSD_i_DBuffOutput
    ' This routine helps simplify the task division with Double size characters 
    for SSD_i_OffsetTemp = 0 to 5
    	SSD_i_DBuffOutput = 0			' clear all bits
    	SSD_i_CharIndex = SSD_i_DBuffInput[SSD_i_OffsetTemp]	' load byte to inspect bits
    for SSD_i_BitOffsetTemp = 0 to 7
    	if SSD_i_CharIndex.0(SSD_i_BitOffsetTemp) = 1 then 	' do we load the bits?
    	SSD_i_CharIndexT = SSD_i_BitOffsetTemp<<1	
    	SSD_i_DBuffOutput.0(SSD_i_CharIndexT) = 1		' set bit to one	
    	SSD_i_CharIndexT = SSD_i_BitOffsetTemp<<1 + 1	
    	SSD_i_DBuffOutput.0(SSD_i_CharIndexT) = 1		' and the one below it because its double size	
    	endif 
    next SSD_i_BitOffsetTemp
    	SSD_i_Byte2Send = SSD_i_DBuffOutput.lowbyte
    	gosub SSD_i_SendData		' Send 1/4 of character out
    	SSD_i_Row = SSD_i_Row + 1
    	gosub SSD_i_SetXY2		' set cursor position
    	SSD_i_Byte2Send = SSD_i_DBuffOutput.Highbyte
    	gosub SSD_i_SendData		' Send 2/4 of character out
    	SSD_i_Row = SSD_i_Row - 1	' go back to top position
    	SSD_i_Column = SSD_i_Column + 1 	' set us up for next column
    	gosub SSD_i_SetXY2		' set cursor position
    	SSD_i_Byte2Send = SSD_i_DBuffOutput.lowbyte
    	gosub SSD_i_SendData		' Send 3/4 of character out
    	SSD_i_Row = SSD_i_Row + 1
    	gosub SSD_i_SetXY2		' set cursor position
    	SSD_i_Byte2Send = SSD_i_DBuffOutput.Highbyte
    	gosub SSD_i_SendData		' Send 4/4 of character out
    	SSD_i_Row = SSD_i_Row - 1
    	SSD_i_Column = SSD_i_Column + 1 	' set us up for next column
    	gosub SSD_i_SetXY2		' set cursor position
    next SSD_i_OffsetTemp
    
    
    return
    '=====================  Send Char  =============================================
    SSD_i_SendChar
    ' This subroutine is run after BuildChar.  SSD_i_DBuffInput must be loaded
    ' This routine helps simplify the task division espically with Double size characters 
    for SSD_i_OffsetTemp = 0 to 5
    	SSD_i_Byte2Send = SSD_i_DBuffInput[SSD_i_OffsetTemp]
    	gosub SSD_i_SendData
    next SSD_i_OffsetTemp
    
    return
    '=====================  Send data  =============================================
    SSD_i_SendData:
    #IFDEF USE_I2C
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,SSD_i_Byte2Send]
    #ELSE
    SSD_DC=1  ' this is DATA not a command
    #IFDEF USE_SPI_SELECT
    SSD_SELECT=0
    #ENDIF
    pauseus 5		' D/C = High for Data. CS is low to connect
    SHIFTOUT MOSI,CLOCK,1,[SSD_i_Byte2Send]
    #ENDIF
    RETURN
    '====================  Send Command  ===========================================
    SSD_i_SendCommand:
    #IFDEF USE_I2C
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DeviceCommand,SSD_i_Byte2Send]
    #ELSE
    SSD_DC=0  ' this is a COMMAND not data
    #IFDEF USE_SPI_SELECT
    SSD_SELECT=0
    #ENDIF
    pauseus 5		' D/C = Low for Commands. CS is low to connect
    SHIFTOUT MOSI,CLOCK,1,[SSD_i_Byte2Send]
    'SHIFTOUT MOSI,CLOCK,1,[SSD_i_DeviceCommand,SSD_i_Byte2Send]
    #ENDIF
    RETURN
    '====================  Send Command  ===========================================
    SSD_i_SendCommand2:
    #IFDEF USE_I2C
    I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DeviceCommand, SSD_i_Byte2Send, SSD_i_Byte2Send2]
    #ELSE
    SSD_DC=0  ' this is a COMMAND not data
    #IFDEF USE_SPI_SELECT
    SSD_SELECT=0
    #ENDIF
    pauseus 5		' D/C = Low for Commands. CS is low to connect
    SHIFTOUT MOSI,CLOCK,1,[SSD_i_Byte2Send, SSD_i_Byte2Send2]
    'SHIFTOUT MOSI,CLOCK,1,[SSD_i_DeviceCommand,SSD_i_Byte2Send, SSD_i_Byte2Send2]
    #ENDIF
    RETURN
    '==============================clear lcd for SSD1306=============================
    SSD_Clear:
    #IFDEF USE_I2C
    FOR SSD_i_CharIndex=0 TO 1023
       	I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,$00]	'Send 0 to every column in every line
    NEXT SSD_i_CharIndex
    #ELSE
    SSD_DC=1	' this is data not a command
    FOR SSD_i_CharIndex=0 TO 1023
    	SHIFTOUT MOSI,CLOCK,1,[$00]
    NEXT SSD_i_CharIndex
    #ENDIF
    SSD_i_Column=0 : SSD_i_Row=0 : gosub SSD_i_SetXY	' Go Home
    RETURN
    
    
    '============================  clear lcd alternate   =============================
    SSD_Clear2:
    #IFDEF USE_I2C
    FOR SSD_i_Row=0 TO 7
    	SSD_i_Byte2Send = $B0 + SSD_i_Row :GOSUB SSD_i_SendCommand	' set correct Page    
    	'SSD_DC=1	' this is data not a command
        FOR SSD_i_OffsetTemp=0 TO 131
        	I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,0]	'Send 0 to every column in every line
        	'SHIFTOUT MOSI,CLOCK,1,[$00]
        NEXT SSD_i_OffsetTemp
    NEXT SSD_i_Row
    #ELSE
    FOR SSD_i_Row=0 TO 7
    	SSD_i_Byte2Send = $B0 + SSD_i_Row :GOSUB SSD_i_SendCommand	' set correct Page    
    	SSD_DC=1	' this is data not a command
        FOR SSD_i_OffsetTemp=0 TO 131
        	'I2CWrite SDA,SCL,SSD_i_Device,[SSD_i_DataCommand,0]	'Send 0 to every column in every line
        	SHIFTOUT MOSI,CLOCK,1,[$00]
        NEXT SSD_i_OffsetTemp
    NEXT SSD_i_Row
    #ENDIF
    SSD_i_Byte2Send=$00:SSD_i_Byte2Send2=$10:GOSUB SSD_i_SendCommand2 ' reset column address
    RETURN
    
    
    '==============================  SET X AND Y  =========================
    SSD_i_SetXY:
    if SSD_i_Row > 8 then SSD_i_Row = 8		' Correct minor errors
    if SSD_i_Column > 127 then SSD_i_Column = 127		
    SSD_i_Byte2Send=$21:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Column:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=127:GOSUB SSD_i_SendCommand
    'Above 3 lines means; Column starts at SSD_i_Column and End at 127
    SSD_i_Byte2Send=$22:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Row:GOSUB SSD_i_SendCommand
    SSD_i_Byte2Send=SSD_i_Row:GOSUB SSD_i_SendCommand
    'Above 3 lines means; Line starts at SSD_i_Row and end at SSD_i_Row,
    'which means ; Only work on specified line!
    RETURN
    '====================  SET X AND Y alternate  =====================
    SSD_i_SetXY2:
    if SSD_i_Row > 8 then SSD_i_Row = 8		' Correct minor errors
    if SSD_i_Column > 127 then SSD_i_Column = 127		
    'SSD_i_Column = SSD_i_Column + 2		' cluge to move the display over to the right a bit
    SSD_i_Byte2Send= $B0 + SSD_i_Row : GOSUB SSD_i_SendCommand		' Set Row
    SSD_i_Byte2Send= SSD_i_Column & $0F : GOSUB SSD_i_SendCommand	' send Low nibble of Column
    SSD_i_Byte2Send= $10 | (SSD_i_Column >> 4) : GOSUB SSD_i_SendCommand  ' send High nibble of Column
    'SSD_i_Column = SSD_i_Column - 2		' move back so program logic is OK
    RETURN
    
    '==========  draw a Horizontal line   ======================
    SSD_PRINTHLine:
    ' Remember this is only Column graphics.  Writing one pixel rewrites the entire Column
    ' Patterns: $1=thin underline the row above, $55= 4 parallel lines, $80= Thin Line just above row below
    ' $0F= 4 Thick line High, $F0= 4 Thick line lower,    
    SSD_i_Column=SSD_BUFF[0]  ' Column in first position
    SSD_i_Row=SSD_BUFF[1]   ' Row in second
    gosub SSD_i_SetXY2		' set cursor position
    SSD_i_OffsetTemp = SSD_BUFF[2]	' ending column   must be < 126
    SSD_i_Byte2Send = SSD_BUFF[3]	'  Pattern to send,  see above
    
    if SSD_i_Column + SSD_i_OffsetTemp > 125 then
    	SSD_i_OffsetTemp =  125 - SSD_i_Column
    endif
    
    For SSD_i_CharIndex=0 To SSD_i_OffsetTemp
    	gosub SSD_i_SendData
    Next SSD_i_CharIndex
    RETURN
    
    '==========  draw a Verticle line   ======================
    SSD_PRINTVLine:
    ' Remember this is only Column graphics.  Writing one pixel rewrites the entire Column
    ' Routine starts from the top and goes down.  This is only a thin (1 pixel) unbroken line
    SSD_i_Column=SSD_BUFF[0]  ' Column to write
    SSD_i_Row=SSD_BUFF[1]   ' Starting Row 
    gosub SSD_i_SetXY2		' set cursor position
    'SSD_BUFF[2] = Starting Height within row  8=top 1=bottom
    'SSD_BUFF[3] = Line Length 1 to n
    if SSD_BUFF[2] < 1 then SSD_BUFF[2] = 1		' Correct minor errors
    if SSD_BUFF[2] > 8 then SSD_BUFF[2] = 8		
    
    
    
    ' First case is a possible short row.   
    SSD_i_Byte2Send = $FF ' start with a full row of pixels
    SSD_i_Byte2Send = SSD_i_Byte2Send << (8-SSD_BUFF[2])	' push down line to proper start value is larger but line is lower
    if SSD_BUFF[3] <= SSD_BUFF[2] then	' if length is <= to height then we need to trim line
    	SSD_BUFF[3] = SSD_BUFF[2] - SSD_BUFF[3] ' get the number to shorten   (did swap 11:38p) 
    	SSD_i_Byte2Send = SSD_i_Byte2Send << SSD_BUFF[3]	' shift the higher (leftmost) values off
    	SSD_i_Byte2Send = SSD_i_Byte2Send >> SSD_BUFF[3]	' go back to what we want
    	gosub SSD_i_SendData	' Send out first row
    	return				' we are done since the line is less than a row
    endif
    gosub SSD_i_SendData	' Send out first row
    SSD_BUFF[3] = SSD_BUFF[3] - SSD_BUFF[2]		' calculate how many pixels we have left
    
    ' Now we loop for the ramaining rows and calculate the last short row if needed.
    SSD_i_PRINTVlineLoop:
    SSD_i_Row = SSD_i_Row + 1
    Gosub SSD_i_SetXY2		' set cursor position to next row
    
    SSD_i_Byte2Send = $FF ' start with a full row of pixels
    if SSD_BUFF[3] < 8 then	' if length is less than height then we need to trim line cause this is the last
    	SSD_BUFF[3] = 8 - SSD_BUFF[3] ' get the number to shorten 
    	SSD_i_Byte2Send = SSD_i_Byte2Send << SSD_BUFF[3]	' shift the higher (leftmost) values off
    	SSD_i_Byte2Send = SSD_i_Byte2Send >> SSD_BUFF[3]	' go back to what we want
    	gosub SSD_i_SendData	' Send out row
    	return				' we are done since the line is less than a row
    endif
    gosub SSD_i_SendData	' Send out next row full row
    SSD_BUFF[3] = SSD_BUFF[3] - 8 		' calculate how many pixels we have left
    goto SSD_i_PRINTVlineLoop	' go back to next lower row
    
    RETURN	' just in case ?
    
    '===========================  Build Character  =======================================
    SSD_i_BuildChar:
    ' Enter this Subroutine with printable character: SSD_i_Char2send
    ' SSD_i_Char2send is subtracted from " " (space char) and * by 5 to be able to index into one table
    
    	SSD_i_OffsetTemp = SSD_i_Char2send - 32	' Space is now at index 0 all other characters are 32 less into index
    	SSD_i_OffsetTemp = SSD_i_OffsetTemp * 5	' Every character is made of 5 bytes
        for SSD_i_CharIndex=SSD_i_OffsetTemp to SSD_i_OffsetTemp+4
        lookup SSD_i_CharIndex,[$00,$00,$00,$00,$00,$00,$00,$5F,$00,$00,$14,$7F,$14,$7F,$14,$00,$08,$07,$03,$00,_	'sp,!,#,"
    					$24,$2A,$7F,$2A,$12,$23,$13,$08,$64,$62,$36,$49,$56,$20,$50,_	'$,%,&
    					$00,$08,$07,$03,$00,$00,$1C,$22,$41,$00,$00,$41,$22,$1C,$00,_	'',(,)
    					$2A,$1C,$7F,$1C,$2A,$08,$08,$3E,$08,$08,$00,$00,$70,$30,$00,_	'*,+,,
    					$08,$08,$08,$08,$08,$00,$00,$60,$60,$00,$20,$10,$08,$04,$02,_	'-,.,/
    					$3E,$51,$49,$45,$3E,$00,$42,$7F,$40,$00,$72,$49,$49,$49,$46,_	'0,1,2
    					$21,$41,$49,$4D,$33,$18,$14,$12,$7F,$10,$27,$45,$45,$45,$39,_	'3,4,5
    					$3C,$4A,$49,$49,$31,$41,$21,$11,$09,$07,$36,$49,$49,$49,$36,_	'6,7,8
    					$46,$49,$49,$29,$1E,$00,$00,$14,$00,$00,$00,$40,$34,$00,$00,_	'9,:,;
    					$00,$08,$14,$22,$41,$14,$14,$14,$14,$14,$00,$41,$22,$14,$08,_	'<,=,>
    					$02,$01,$59,$09,$06,$3E,$41,$5D,$59,$4E,$7C,$12,$11,$12,$7C,_	'?,@,A
    					$7F,$49,$49,$49,$36,$3E,$41,$41,$41,$22,$7F,$41,$41,$41,$3E,_	'B,C,D
    					$7F,$49,$49,$49,$41,$7F,$09,$09,$09,$01,$3E,$41,$41,$51,$73,_	'E,F,G
    					$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$20,$40,$41,$3F,$01,_	'H,I,J
    					$7F,$08,$14,$22,$41,$7F,$40,$40,$40,$40,$7F,$02,$1C,$02,$7F,_	'K,L,M
    					$7F,$04,$08,$10,$7F,$3E,$41,$41,$41,$3E,$7F,$09,$09,$09,$06,_	'N,O,P
    					$3E,$41,$51,$21,$5E,$7F,$09,$19,$29,$46,$26,$49,$49,$49,$32,_	'Q,R,S
    					$03,$01,$7F,$01,$03,$3F,$40,$40,$40,$3F,$1F,$20,$40,$20,$1F,_	'T,U,V
    					$3F,$40,$38,$40,$3F,$63,$14,$08,$14,$63,$03,$04,$78,$04,$03,_	'W,X,Y
    					$61,$59,$49,$4D,$43,$00,$7F,$41,$41,$41,$02,$04,$08,$10,$20,_	'Z,[,\
    					$00,$41,$41,$41,$7F,$04,$02,$01,$02,$04,$40,$40,$40,$40,$40,_	'],^,_
    					$00,$03,$07,$08,$00,$20,$54,$54,$38,$40,$7F,$28,$44,$44,$38,_	'`,a,b
    					$38,$44,$44,$44,$28,$38,$44,$44,$28,$7F,$38,$54,$54,$54,$18,_	'c,d,e
    					$00,$08,$7E,$09,$02,$0C,$52,$52,$4A,$3C,$7F,$08,$04,$04,$78,_	'f,g,h
    					$00,$44,$7D,$40,$00,$20,$40,$40,$3D,$00,$7F,$10,$28,$44,$00,_	'i,j,k
    					$00,$41,$7F,$40,$00,$7C,$04,$78,$04,$78,$7C,$08,$04,$04,$78,_	'l,m,n
    					$38,$44,$44,$44,$38,$7C,$18,$24,$24,$18,$18,$24,$24,$18,$7C,_	'o,p,q
    					$7C,$08,$04,$04,$08,$48,$54,$54,$54,$24,$04,$04,$3F,$44,$24,_	'r,s,t
    					$3C,$40,$40,$20,$7C,$1C,$20,$40,$20,$1C,$3C,$40,$30,$40,$3C,_	'u,v,w
    					$44,$28,$10,$28,$44,$4C,$50,$50,$50,$3C,$44,$64,$54,$4C,$44,_	'x,y,z
    					$00,$08,$36,$41,$00,$00,$00,$77,$00,$00,$00,$41,$36,$08,$00,_	'{,|,}
    					$02,$01,$02,$04,$02],SSD_i_Byte2Send	'~
    
    	SSD_i_DBuffInput[SSD_i_CharIndex - SSD_i_OffsetTemp] = SSD_i_Byte2Send		' load char bytes into array
    next SSD_i_CharIndex
    SSD_i_Byte2Send = $00		' space between characters always $00
    SSD_i_DBuffInput[5] = $00		' load final char byte into array
    return
    '===============================================================================
    SSD1306_i_Around:

  6. #6
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: SSD1306 Include example

    Here is a pic of the output:

    Name:  96 Display.jpg
Views: 2137
Size:  32.3 KB

  7. #7
    Join Date
    Apr 2013
    Posts
    32

    Default Re: SSD1306 Include example

    Great job

  8. #8

    Default Re: SSD1306 Include example

    Hi Tim

    I don't have "LABx1.inc", where can I get it?

    George

  9. #9
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: SSD1306 Include example

    George,
    Labx1.inc is just a hardware abstraction include. It helps make testing on different hardware easy.
    Since we are not using any LED's, LCD's or analog you can delete the Include and compile successfully with only adding:
    ===> DEFINE OSC 20
    or whatever speed you are currently using.

    If you are using analog pins you may also need to include something like DT's "AllDigital" about 3/4 of the way down the page.
    http://www.picbasic.co.uk/forum/show...ght=alldigital

    Regards
    Tim

  10. #10
    Join Date
    Sep 2005
    Location
    France
    Posts
    50

    Default Re: SSD1306 Include example

    Hi timc

    I know this is an old thread... I'm using some parts of your code (first one with small characters). Just changing Init because it doesn't work with my chineese LCD, and added a clear screen because some persistent pixels everywhere when choosing invert display.
    Now it works fine... Just a problem with, I think, speed.
    Using a PIC18F46K22 at 12MHz = ok Same pic at 12MHz x 4 PLL = 48MHz and the display won't go to specific row and line.
    tried : DEFINE SHIFT_PAUSEUS 4 but doesn't work too.
    Someone can help ?
    Regards
    Last edited by harryweb; - 26th November 2017 at 19:09. Reason: add info

  11. #11
    Join Date
    Apr 2014
    Location
    Northeast
    Posts
    395

    Default Re: SSD1306 Include example

    Did you include the statement, "DEFINE OSC 48" so PBP knows how to time things?

  12. #12
    Join Date
    Sep 2005
    Location
    France
    Posts
    50

    Default Re: SSD1306 Include example

    Yes I did....
    Can't explain this. So... Now I'm using second code source with BIG characters... Working at 48 MHz !

Similar Threads

  1. Use of INCLUDE
    By Alexey in forum mel PIC BASIC
    Replies: 8
    Last Post: - 25th December 2013, 13:51
  2. Help With OLED Display / 128X64 SSD1306
    By Denner in forum General
    Replies: 6
    Last Post: - 25th May 2013, 15:40
  3. Where are all the INCLUDE files??
    By Heckler in forum General
    Replies: 3
    Last Post: - 13th September 2011, 08:27
  4. can't find include file!
    By jimbostlawrence in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 10th November 2009, 08:44
  5. Need to download Include files
    By laflam_p in forum Off Topic
    Replies: 2
    Last Post: - 2nd September 2009, 13:39

Tags for this Thread

Posting Permissions

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