PDA

View Full Version : SSD1306 Include example



timc
- 19th July 2015, 02:38
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



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

sleep 5
GOTO looper
END


Now The Include



'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,$0 0,$07,$00,$14,$7F,$14,$7F,$14,_ 'sp,!,",#
$24,$2A,$7F,$2A,$12,$23,$13,$08,$64,$62,$36,$49,$5 6,$20,$50,_ '$,%,&
$00,$08,$07,$03,$00,$00,$1C,$22,$41,$00,$00,$41,$2 2,$1C,$00,_ '',(,)
$2A,$1C,$7F,$1C,$2A,$08,$08,$3E,$08,$08,$00,$00,$7 0,$30,$00,_ '*,+,,
$08,$08,$08,$08,$08,$00,$00,$60,$60,$00,$20,$10,$0 8,$04,$02,_ '-,.,/
$3E,$51,$49,$45,$3E,$00,$42,$7F,$40,$00,$72,$49,$4 9,$49,$46,_ '0,1,2
$21,$41,$49,$4D,$33,$18,$14,$12,$7F,$10,$27,$45,$4 5,$45,$39,_ '3,4,5
$3C,$4A,$49,$49,$31,$41,$21,$11,$09,$07,$36,$49,$4 9,$49,$36,_ '6,7,8
$46,$49,$49,$29,$1E,$00,$00,$14,$00,$00,$00,$40,$3 4,$00,$00,_ '9,:,;
$00,$08,$14,$22,$41,$14,$14,$14,$14,$14,$00,$41,$2 2,$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,$4 1,$41,$3E,_ 'B,C,D
$7F,$49,$49,$49,$41,$7F,$09,$09,$09,$01,$3E,$41,$4 1,$51,$73,_ 'E,F,G
$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$20,$40,$4 1,$3F,$01,_ 'H,I,J
$7F,$08,$14,$22,$41,$7F,$40,$40,$40,$40,$7F,$02,$1 C,$02,$7F,_ 'K,L,M
$7F,$04,$08,$10,$7F,$3E,$41,$41,$41,$3E,$7F,$09,$0 9,$09,$06,_ 'N,O,P
$3E,$41,$51,$21,$5E,$7F,$09,$19,$29,$46,$26,$49,$4 9,$49,$32,_ 'Q,R,S
$03,$01,$7F,$01,$03,$3F,$40,$40,$40,$3F,$1F,$20,$4 0,$20,$1F,_ 'T,U,V
$3F,$40,$38,$40,$3F,$63,$14,$08,$14,$63,$03,$04,$7 8,$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,$4 0,$40,$40,_ '],^,_
$00,$03,$07,$08,$00,$20,$54,$54,$38,$40,$7F,$28,$4 4,$44,$38,_ '`,a,b
$38,$44,$44,$44,$28,$38,$44,$44,$28,$7F,$38,$54,$5 4,$54,$18,_ 'c,d,e
$00,$08,$7E,$09,$02,$0C,$52,$52,$4A,$3C,$7F,$08,$0 4,$04,$78,_ 'f,g,h
$00,$44,$7D,$40,$00,$20,$40,$40,$3D,$00,$7F,$10,$2 8,$44,$00,_ 'i,j,k
$00,$41,$7F,$40,$00,$7C,$04,$78,$04,$78,$7C,$08,$0 4,$04,$78,_ 'l,m,n
$38,$44,$44,$44,$38,$7C,$18,$24,$24,$18,$18,$24,$2 4,$18,$7C,_ 'o,p,q
$7C,$08,$04,$04,$08,$48,$54,$54,$54,$24,$04,$04,$3 F,$44,$24,_ 'r,s,t
$3C,$40,$40,$20,$7C,$1C,$20,$40,$20,$1C,$3C,$40,$3 0,$40,$3C,_ 'u,v,w
$44,$28,$10,$28,$44,$4C,$50,$50,$50,$3C,$44,$64,$5 4,$4C,$44,_ 'x,y,z
$00,$08,$36,$41,$00,$00,$00,$77,$00,$00,$00,$41,$3 6,$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:

timc
- 21st July 2015, 04:41
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:



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



'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,$0 0,$07,$00,$14,$7F,$14,$7F,$14,_ 'sp,!,",#
$24,$2A,$7F,$2A,$12,$23,$13,$08,$64,$62,$36,$49,$5 6,$20,$50,_ '$,%,&
$00,$08,$07,$03,$00,$00,$1C,$22,$41,$00,$00,$41,$2 2,$1C,$00,_ '',(,)
$2A,$1C,$7F,$1C,$2A,$08,$08,$3E,$08,$08,$00,$00,$7 0,$30,$00,_ '*,+,,
$08,$08,$08,$08,$08,$00,$00,$60,$60,$00,$20,$10,$0 8,$04,$02,_ '-,.,/
$3E,$51,$49,$45,$3E,$00,$42,$7F,$40,$00,$72,$49,$4 9,$49,$46,_ '0,1,2
$21,$41,$49,$4D,$33,$18,$14,$12,$7F,$10,$27,$45,$4 5,$45,$39,_ '3,4,5
$3C,$4A,$49,$49,$31,$41,$21,$11,$09,$07,$36,$49,$4 9,$49,$36,_ '6,7,8
$46,$49,$49,$29,$1E,$00,$00,$14,$00,$00,$00,$40,$3 4,$00,$00,_ '9,:,;
$00,$08,$14,$22,$41,$14,$14,$14,$14,$14,$00,$41,$2 2,$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,$4 1,$41,$3E,_ 'B,C,D
$7F,$49,$49,$49,$41,$7F,$09,$09,$09,$01,$3E,$41,$4 1,$51,$73,_ 'E,F,G
$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$20,$40,$4 1,$3F,$01,_ 'H,I,J
$7F,$08,$14,$22,$41,$7F,$40,$40,$40,$40,$7F,$02,$1 C,$02,$7F,_ 'K,L,M
$7F,$04,$08,$10,$7F,$3E,$41,$41,$41,$3E,$7F,$09,$0 9,$09,$06,_ 'N,O,P
$3E,$41,$51,$21,$5E,$7F,$09,$19,$29,$46,$26,$49,$4 9,$49,$32,_ 'Q,R,S
$03,$01,$7F,$01,$03,$3F,$40,$40,$40,$3F,$1F,$20,$4 0,$20,$1F,_ 'T,U,V
$3F,$40,$38,$40,$3F,$63,$14,$08,$14,$63,$03,$04,$7 8,$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,$4 0,$40,$40,_ '],^,_
$00,$03,$07,$08,$00,$20,$54,$54,$38,$40,$7F,$28,$4 4,$44,$38,_ '`,a,b
$38,$44,$44,$44,$28,$38,$44,$44,$28,$7F,$38,$54,$5 4,$54,$18,_ 'c,d,e
$00,$08,$7E,$09,$02,$0C,$52,$52,$4A,$3C,$7F,$08,$0 4,$04,$78,_ 'f,g,h
$00,$44,$7D,$40,$00,$20,$40,$40,$3D,$00,$7F,$10,$2 8,$44,$00,_ 'i,j,k
$00,$41,$7F,$40,$00,$7C,$04,$78,$04,$78,$7C,$08,$0 4,$04,$78,_ 'l,m,n
$38,$44,$44,$44,$38,$7C,$18,$24,$24,$18,$18,$24,$2 4,$18,$7C,_ 'o,p,q
$7C,$08,$04,$04,$08,$48,$54,$54,$54,$24,$04,$04,$3 F,$44,$24,_ 'r,s,t
$3C,$40,$40,$20,$7C,$1C,$20,$40,$20,$1C,$3C,$40,$3 0,$40,$3C,_ 'u,v,w
$44,$28,$10,$28,$44,$4C,$50,$50,$50,$3C,$44,$64,$5 4,$4C,$44,_ 'x,y,z
$00,$08,$36,$41,$00,$00,$00,$77,$00,$00,$00,$41,$3 6,$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:

elcrcp
- 27th July 2015, 19:28
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


'=================== 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,$0 0,$07,$00,$14,$7F,$14,$7F,$14,_ 'sp,!,",#
$24,$2A,$7F,$2A,$12,$23,$13,$08,$64,$62,$36,$49,$5 6,$20,$50,_ '$,%,&
$00,$08,$07,$03,$00,$00,$1C,$22,$41,$00,$00,$41,$2 2,$1C,$00,_ '',(,)
$2A,$1C,$7F,$1C,$2A,$08,$08,$3E,$08,$08,$00,$00,$7 0,$30,$00,_ '*,+,,
$08,$08,$08,$08,$08,$00,$00,$60,$60,$00,$20,$10,$0 8,$04,$02,_ '-,.,/
$3E,$51,$49,$45,$3E,$00,$42,$7F,$40,$00,$72,$49,$4 9,$49,$46,_ '0,1,2
$21,$41,$49,$4D,$33,$18,$14,$12,$7F,$10,$27,$45,$4 5,$45,$39,_ '3,4,5
$3C,$4A,$49,$49,$31,$41,$21,$11,$09,$07,$36,$49,$4 9,$49,$36,_ '6,7,8
$46,$49,$49,$29,$1E,$00,$00,$14,$00,$00,$00,$40,$3 4,$00,$00,_ '9,:,;
$00,$08,$14,$22,$41,$14,$14,$14,$14,$14,$00,$41,$2 2,$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,$4 1,$41,$3E,_ 'B,C,D
$7F,$49,$49,$49,$41,$7F,$09,$09,$09,$01,$3E,$41,$4 1,$51,$73,_ 'E,F,G
$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$20,$40,$4 1,$3F,$01,_ 'H,I,J
$7F,$08,$14,$22,$41,$7F,$40,$40,$40,$40,$7F,$02,$1 C,$02,$7F,_ 'K,L,M
$7F,$04,$08,$10,$7F,$3E,$41,$41,$41,$3E,$7F,$09,$0 9,$09,$06,_ 'N,O,P
$3E,$41,$51,$21,$5E,$7F,$09,$19,$29,$46,$26,$49,$4 9,$49,$32,_ 'Q,R,S
$03,$01,$7F,$01,$03,$3F,$40,$40,$40,$3F,$1F,$20,$4 0,$20,$1F,_ 'T,U,V
$3F,$40,$38,$40,$3F,$63,$14,$08,$14,$63,$03,$04,$7 8,$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,$4 0,$40,$40,_ '],^,_
$00,$03,$07,$08,$00,$20,$54,$54,$38,$40,$7F,$28,$4 4,$44,$38,_ '`,a,b
$38,$44,$44,$44,$28,$38,$44,$44,$28,$7F,$38,$54,$5 4,$54,$18,_ 'c,d,e
$00,$08,$7E,$09,$02,$0C,$52,$52,$4A,$3C,$7F,$08,$0 4,$04,$78,_ 'f,g,h
$00,$44,$7D,$40,$00,$20,$40,$40,$3D,$00,$7F,$10,$2 8,$44,$00,_ 'i,j,k
$00,$41,$7F,$40,$00,$7C,$04,$78,$04,$78,$7C,$08,$0 4,$04,$78,_ 'l,m,n
$38,$44,$44,$44,$38,$7C,$18,$24,$24,$18,$18,$24,$2 4,$18,$7C,_ 'o,p,q
$7C,$08,$04,$04,$08,$48,$54,$54,$54,$24,$04,$04,$3 F,$44,$24,_ 'r,s,t
$3C,$40,$40,$20,$7C,$1C,$20,$40,$20,$1C,$3C,$40,$3 0,$40,$3C,_ 'u,v,w
$44,$28,$10,$28,$44,$4C,$50,$50,$50,$3C,$44,$64,$5 4,$4C,$44,_ 'x,y,z
$00,$08,$36,$41,$00,$00,$00,$77,$00,$00,$00,$41,$3 6,$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:

timc
- 30th July 2015, 05:38
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:



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.

timc
- 8th August 2015, 04:48
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



'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




'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,$1 4,$7F,$14,$00,$08,$07,$03,$00,_ 'sp,!,#,"
$24,$2A,$7F,$2A,$12,$23,$13,$08,$64,$62,$36,$49,$5 6,$20,$50,_ '$,%,&
$00,$08,$07,$03,$00,$00,$1C,$22,$41,$00,$00,$41,$2 2,$1C,$00,_ '',(,)
$2A,$1C,$7F,$1C,$2A,$08,$08,$3E,$08,$08,$00,$00,$7 0,$30,$00,_ '*,+,,
$08,$08,$08,$08,$08,$00,$00,$60,$60,$00,$20,$10,$0 8,$04,$02,_ '-,.,/
$3E,$51,$49,$45,$3E,$00,$42,$7F,$40,$00,$72,$49,$4 9,$49,$46,_ '0,1,2
$21,$41,$49,$4D,$33,$18,$14,$12,$7F,$10,$27,$45,$4 5,$45,$39,_ '3,4,5
$3C,$4A,$49,$49,$31,$41,$21,$11,$09,$07,$36,$49,$4 9,$49,$36,_ '6,7,8
$46,$49,$49,$29,$1E,$00,$00,$14,$00,$00,$00,$40,$3 4,$00,$00,_ '9,:,;
$00,$08,$14,$22,$41,$14,$14,$14,$14,$14,$00,$41,$2 2,$14,$08,_ '<,=,>
$02,$01,$59,$09,$06,$3E,$41,$5D,$59,$4E,$7C,$12,$1 1,$12,$7C,_ '?,@,A
$7F,$49,$49,$49,$36,$3E,$41,$41,$41,$22,$7F,$41,$4 1,$41,$3E,_ 'B,C,D
$7F,$49,$49,$49,$41,$7F,$09,$09,$09,$01,$3E,$41,$4 1,$51,$73,_ 'E,F,G
$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$20,$40,$4 1,$3F,$01,_ 'H,I,J
$7F,$08,$14,$22,$41,$7F,$40,$40,$40,$40,$7F,$02,$1 C,$02,$7F,_ 'K,L,M
$7F,$04,$08,$10,$7F,$3E,$41,$41,$41,$3E,$7F,$09,$0 9,$09,$06,_ 'N,O,P
$3E,$41,$51,$21,$5E,$7F,$09,$19,$29,$46,$26,$49,$4 9,$49,$32,_ 'Q,R,S
$03,$01,$7F,$01,$03,$3F,$40,$40,$40,$3F,$1F,$20,$4 0,$20,$1F,_ 'T,U,V
$3F,$40,$38,$40,$3F,$63,$14,$08,$14,$63,$03,$04,$7 8,$04,$03,_ 'W,X,Y
$61,$59,$49,$4D,$43,$00,$7F,$41,$41,$41,$02,$04,$0 8,$10,$20,_ 'Z,[,\
$00,$41,$41,$41,$7F,$04,$02,$01,$02,$04,$40,$40,$4 0,$40,$40,_ '],^,_
$00,$03,$07,$08,$00,$20,$54,$54,$38,$40,$7F,$28,$4 4,$44,$38,_ '`,a,b
$38,$44,$44,$44,$28,$38,$44,$44,$28,$7F,$38,$54,$5 4,$54,$18,_ 'c,d,e
$00,$08,$7E,$09,$02,$0C,$52,$52,$4A,$3C,$7F,$08,$0 4,$04,$78,_ 'f,g,h
$00,$44,$7D,$40,$00,$20,$40,$40,$3D,$00,$7F,$10,$2 8,$44,$00,_ 'i,j,k
$00,$41,$7F,$40,$00,$7C,$04,$78,$04,$78,$7C,$08,$0 4,$04,$78,_ 'l,m,n
$38,$44,$44,$44,$38,$7C,$18,$24,$24,$18,$18,$24,$2 4,$18,$7C,_ 'o,p,q
$7C,$08,$04,$04,$08,$48,$54,$54,$54,$24,$04,$04,$3 F,$44,$24,_ 'r,s,t
$3C,$40,$40,$20,$7C,$1C,$20,$40,$20,$1C,$3C,$40,$3 0,$40,$3C,_ 'u,v,w
$44,$28,$10,$28,$44,$4C,$50,$50,$50,$3C,$44,$64,$5 4,$4C,$44,_ 'x,y,z
$00,$08,$36,$41,$00,$00,$00,$77,$00,$00,$00,$41,$3 6,$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:

timc
- 8th August 2015, 04:50
Here is a pic of the output:

7975

elcrcp
- 17th August 2015, 00:06
Great job :rolleyes:

towlerg
- 17th August 2015, 00:37
Hi Tim

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

George

timc
- 17th August 2015, 04:07
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/showthread.php?t=19638&highlight=alldigital

Regards
Tim

harryweb
- 26th November 2017, 19:01
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

mpgmike
- 27th November 2017, 01:46
Did you include the statement, "DEFINE OSC 48" so PBP knows how to time things?

harryweb
- 28th November 2017, 08:53
Yes I did....
Can't explain this. So... Now I'm using second code source with BIG characters... Working at 48 MHz !