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,"{}[]!@#$%^&*()  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: