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