'Oled Subroutines

'VlaM ========================= Constants =======================================

Const Oled$addr_w = &B01111000       ' OLED write address (connect DC pin to GND)
Const Oled$addr_r = &B01111001       ' OLED read address (connect DC pin to GND)

'VlaM ======================== OLED subroutines =================================

'VlaM ======================== HW OLED reset ====================================

Sub Oled$reset
   Oled$reset_pin = 0         'reset
   Waitms 5
   Oled$reset_pin = 1         'end of reset
   Waitms 5
   Oled$send_cmd &HC8         'Set_Comm_Output_Scan_Dir
   Oled$send_cmd &HA1         'Set_Segment_Remap
   Oled$send_cmd &HAF         'Set_display_on
End Sub

'VlaM ======================== Clear OLED =======================================

Sub Oled$clear

Local Oled$page As Byte , Oled$col As Byte

For Oled$page = &HB0 To &HB7  'for pages 0 to 7
   Oled$send_cmd Oled$page    'send page address
   Oled$send_cmd &H10         'send 1st column address = 2
   Oled$send_cmd &H02

   I2cstart                   'start condition
   I2cwbyte Oled$addr_w       'OLED write address
   I2cwbyte &B01000000        'next bytes are data bytes

   For Oled$col = 0 To 127    'clear page
      I2cwbyte &B00000000
   Next
   I2cstop                    'stop condition
Next
End Sub

'VlaM ======================== Sends command to OLED ============================

Sub Oled$send_cmd(byval Oled$outbyte As Byte )

I2cstart                      'start condition
I2cwbyte Oled$addr_w          'OLED write address
I2cwbyte &B10000000           'next byte is a command byte
I2cwbyte Oled$outbyte         'send a command to OLED
I2cstop                       'stop condition

End Sub

'VlaM ======================== Sends data byte to OLED ==========================

Sub Oled$send_dta(byval Oled$outbyte As Byte )

I2cstart                      'start condition
I2cwbyte Oled$addr_w          'OLED write address
I2cwbyte &B01000000           'next byte is a data byte
I2cwbyte Oled$outbyte         'send a data byte to OLED
I2cstop                       'stop condition

End Sub

'VlaM ======================= Reads data byte from OLED =========================

Sub Oled$read_byte(byref Oled$byte As Byte , Byval Oled$page As Byte , Byval Oled$col As Byte )

Oled$$set_adr Oled$page , Oled$col       'set OLED address

I2cwbyte &B01000000           'instruct OLED to send data bytes
I2cstart                      'start condition
I2cwbyte Oled$addr_r          'OLED read address
I2crbyte Oled$byte , Ack      'dummy read
I2crbyte Oled$byte , Nack     'read a byte
I2cstop                       'stop condition

End Sub

'VlaM ====================== Sends data byte to OLED ============================

Sub Oled$write_byte(byval Oled$byte_to_send As Byte , Byval Oled$page As Byte , Byval Oled$col As Byte)

Oled$$set_adr Oled$page , Oled$col       'set OLED address

I2cwbyte &B01000000           'next byte is a data byte
I2cwbyte Oled$byte_to_send    'send a data byte to OLED
I2cstop                       'stop condition

End Sub

'VlaM ==================== Set OLED pixel ON/OFF ================================

Sub Oled$set_pix(byval Oled$bit_value As Byte , Byval Oled$row As Byte , Byval Oled$col As Byte)

Local Oled$page As Byte , Oled$bit As Byte , Oled$byte As Byte

   Oled$bit = Oled$row And &B00000111       'calculate row/page address
   Oled$page = Oled$row / 8

   Oled$$set_adr Oled$page , Oled$col       'set OLED address

   I2cwbyte &B01000000        'instruct OLED to send data bytes
   I2cstart                   'start condition
   I2cwbyte Oled$addr_r       'OLED read address
   I2crbyte Oled$byte , Ack   'dummy read
   I2crbyte Oled$byte , Nack  'read a byte
   Oled$byte.oled$bit = Oled$bit_value.0       'set pixel ON/OFF

   Oled$$set_adr Oled$page , Oled$col       'set OLED address
   I2cwbyte &B01000000        'next byte is a data byte
   I2cwbyte Oled$byte         'write edited byte back to OLED
   I2cstop                    'stop condition

End Sub

'VlaM ==================== Set OLED pixel ON ====================================

Sub Oled$set_pix_on(byval Oled$row As Byte , Byval Oled$col As Byte)

Local Oled$page As Byte , Oled$bit As Byte , Oled$byte As Byte

   Oled$bit = Oled$row And &B00000111       'calculate row/page address
   Oled$page = Oled$row / 8

   Oled$$set_adr Oled$page , Oled$col       'set OLED address

   I2cwbyte &B01000000        'instruct OLED to send data bytes
   I2cstart                   'start condition
   I2cwbyte Oled$addr_r       'OLED read address
   I2crbyte Oled$byte , Ack   'dummy read
   I2crbyte Oled$byte , Nack  'read a byte
   Set Oled$byte.oled$bit     'set pixel ON

   Oled$$set_adr Oled$page , Oled$col       'set OLED address
   I2cwbyte &B01000000        'next byte is a data byte
   I2cwbyte Oled$byte         'write edited byte back to OLED
   I2cstop                    'stop condition

End Sub

'VlaM ==================== Set OLED pixel OFF ===================================

Sub Oled$set_pix_off(byval Oled$row As Byte , Byval Oled$col As Byte )

Local Oled$page As Byte , Oled$bit As Byte , Oled$byte As Byte

   Oled$bit = Oled$row And &B00000111       'calculate row/page address
   Oled$page = Oled$row / 8

   Oled$$set_adr Oled$page , Oled$col       'set OLED address

   I2cwbyte &B01000000        'instruct OLED to send data bytes
   I2cstart                   'start condition
   I2cwbyte Oled$addr_r       'OLED read address
   I2crbyte Oled$byte , Ack   'dummy read
   I2crbyte Oled$byte , Nack  'read a byte
   Reset Oled$byte.oled$bit   'set pixel OFF

   Oled$$set_adr Oled$page , Oled$col       'set OLED address
   I2cwbyte &B01000000        'next byte is a data byte
   I2cwbyte Oled$byte         'write edited byte back to OLED
   I2cstop                    'stop condition

End Sub

'VlaM ======================== Sends text to OLED ===============================

Sub Oled$write_text(byval Oled$text_to_write As String * 22 , Byval Oled$page As Byte , Byval Oled$col As Byte)
Local Oled$char_to_write As String * 1
Local Oled$temp1 As Byte , Oled$temp2 As Word , Oled$temp3 As Byte

Oled$$set_adr Oled$page , Oled$col       'set OLED address
I2cwbyte &B01000000           'next bytes are data bytes

For Oled$temp1 = 1 To Len(oled$text_to_write)
   Oled$char_to_write = Mid(oled$text_to_write , Oled$temp1 , 1)       'select next char from string
   Oled$temp3 = Asc(oled$char_to_write)       'determine its ASCII value
   If Oled$temp3 >= 128 Then  'if Њ, read its ASCII value from table
      Oled$temp3 = Lookdown(oled$temp3 , Oled$char_table_1 , 10) + 127
   End If

   Oled$temp3 = Oled$temp3 - 32
   Oled$temp2 = Oled$temp3 * 5

   Oled$temp3 = Lookup(oled$temp2 , Oled$char_table)       'read from Char_table pixel pattern (one col)
   I2cwbyte Oled$temp3

   lpm _temp1, z+
   I2cwbyte _temp1
   lpm _temp1, z+
   I2cwbyte _temp1
   lpm _temp1, z+
   I2cwbyte _temp1
   lpm _temp1, z+
   I2cwbyte _temp1

   I2cwbyte &B00000000        'send empty col to OLED (space before next char)
Next

I2cstop                       'stop condition
Goto Oled$write_text_ex

Oled$char_table:              'pixel patterns of supported characters
Data 0 , 0 , 0 , 0 , 0        '
Data 0 , 0 , 95 , 0 , 0       ' !
Data 3 , 7 , 0 , 3 , 7 ' "
Data 36 , 126 , 36 , 126 , 36 ' #
Data 36 , 43 , 106 , 18 , 0   ' $
Data 99 , 19 , 8 , 100 , 99   ' %
Data 54 , 73 , 86 , 32 , 80   ' &
Data 0 , 3 , 7 , 0 , 0        ' '
Data 0 , 62 , 65 , 0 , 0      ' (
Data 0 , 65 , 62 , 0 , 0      ' )
Data 8 , 62 , 28 , 62 , 8     ' *
Data 8 , 8 , 62 , 8 , 8       ' +
Data 0 , 96 , 224 , 0 , 0     ' ,
Data 8 , 8 , 8 , 8 , 8        ' -
Data 0 , 0 , 96 , 96 , 0      ' ;
Data 32 , 16 , 8 , 4 , 2      ' /
Data 62 , 81 , 73 , 69 , 62   ' 0
Data 0 , 66 , 127 , 64 , 0    ' 1
Data 98 , 81 , 73 , 73 , 70   ' 2
Data 34 , 73 , 73 , 73 , 54   ' 3
Data 24 , 20 , 18 , 127 , 16  ' 4
Data 47 , 73 , 73 , 73 , 49   ' 5
Data 60 , 74 , 73 , 73 , 48   ' 6
Data 1 , 113 , 9 , 5 , 3      ' 7
Data 54 , 73 , 73 , 73 , 54   ' 8
Data 6 , 73 , 73 , 41 , 30    ' 9
Data 0 , 0 , 108 , 108 , 0    ' :
Data 0 , 0 , 108 , 236 , 0    ' ;
Data 8 , 20 , 34 , 65 , 0     ' <
Data 36 , 36 , 36 , 36 , 36   ' =
Data 0 , 65 , 34 , 20 , 8     ' >
Data 2 , 1 , 89 , 9 , 6       ' ?
Data 62 , 65 , 93 , 85 , 30   ' @
Data 126 , 17 , 17 , 17 , 126 ' A
Data 127 , 73 , 73 , 73 , 54  ' B
Data 62 , 65 , 65 , 65 , 34   ' C
Data 127 , 65 , 65 , 65 , 62  ' D
Data 127 , 73 , 73 , 73 , 65  ' E
Data 127 , 9 , 9 , 9 , 1      ' F
Data 62 , 65 , 73 , 73 , 122  ' G
Data 127 , 8 , 8 , 8 , 127    ' H
Data 0 , 65 , 127 , 65 , 0    ' I
Data 48 , 64 , 64 , 64 , 63   ' J
Data 127 , 8 , 20 , 34 , 65   ' K
Data 127 , 64 , 64 , 64 , 64  ' L
Data 127 , 2 , 4 , 2 , 127    ' M
Data 127 , 2 , 4 , 8 , 127    ' N
Data 62 , 65 , 65 , 65 , 62   ' O
Data 127 , 9 , 9 , 9 , 6      ' P
Data 62 , 65 , 81 , 33 , 94   ' Q
Data 127 , 9 , 9 , 25 , 102   ' R
Data 38 , 73 , 73 , 73 , 50   ' S
Data 1 , 1 , 127 , 1 , 1      ' T
Data 63 , 64 , 64 , 64 , 63   ' U
Data 31 , 32 , 64 , 32 , 31   ' V
Data 63 , 64 , 60 , 64 , 63   ' W
Data 99 , 20 , 8 , 20 , 99    ' X
Data 7 , 8 , 112 , 8 , 7      ' Y
Data 113 , 73 , 69 , 67 , 0   ' Z
Data 0 , 127 , 65 , 65 , 0    ' [
Data 2 , 4 , 8 , 16 , 32      ' \
Data 0 , 65 , 65 , 127 , 0    ' ]
Data 4 , 2 , 1 , 2 , 4        ' ^
Data 128 , 128 , 128 , 128 , 128       ' _
Data 0 , 3 , 7 , 0 , 0        ' `
Data 32 , 84 , 84 , 84 , 120  ' a
Data 127 , 68 , 68 , 68 , 56  ' b
Data 56 , 68 , 68 , 68 , 40   ' c
Data 56 , 68 , 68 , 68 , 127  ' d
Data 56 , 84 , 84 , 84 , 8    ' e
Data 8 , 126 , 9 , 9 , 0      ' f
Data 24 , 164 , 164 , 164 , 124       ' g
Data 127 , 4 , 4 , 120 , 0    ' h
Data 0 , 68 , 125 , 64 , 0    ' i
Data 64 , 128 , 132 , 125 , 0 ' j
Data 127 , 16 , 40 , 68 , 0   ' k
Data 0 , 65 , 127 , 64 , 0    ' l
Data 124 , 4 , 24 , 4 , 120   ' m
Data 124 , 4 , 4 , 120 , 0    ' n
Data 56 , 68 , 68 , 68 , 56   ' o
Data 252 , 68 , 68 , 68 , 56  ' p
Data 56 , 68 , 68 , 68 , 252  ' q
Data 68 , 120 , 68 , 4 , 8    ' r
Data 8 , 84 , 84 , 84 , 32    ' s
Data 4 , 62 , 68 , 36 , 0     ' t
Data 60 , 64 , 32 , 124 , 0   ' u
Data 28 , 32 , 64 , 32 , 28   ' v
Data 60 , 96 , 48 , 96 , 60   ' w
Data 108 , 16 , 16 , 108 , 0  ' x
Data 156 , 160 , 96 , 60 , 0  ' y
Data 100 , 84 , 84 , 76 , 0   ' z
Data 8 , 62 , 65 , 65 , 0     ' {
Data 0 , 0 , 119 , 0 , 0      ' |
Data 0 , 65 , 65 , 62 , 8     ' }
Data 2 , 1 , 2 , 1 , 0        ' ~
Data 0 , 255 , 255 , 255 , 0  ' 
Data 60 , 67 , 66 , 67 , 36   ' 
Data 60 , 66 , 66 , 67 , 36   ' 
Data 127 , 73 , 65 , 65 , 62  ' 
Data 36 , 75 , 74 , 75 , 52   ' 
Data 98 , 83 , 74 , 71 , 66   ' 
Data 56 , 70 , 68 , 70 , 40   ' 
Data 56 , 68 , 68 , 70 , 40   ' 
Data 48 , 72 , 72 , 74 , 127  ' 
Data 8 , 86 , 84 , 86 , 32    ' 
Data 100 , 86 , 84 , 78 , 68  ' 

Oled$char_table_1:            'Auxiliary table for Њ, helps to determine its ASCII values
Data "Њ"

Oled$write_text_ex:
End Sub

'VlaM =================== Sets OLED row&col address =============================

Sub Oled$$set_adr(byval Oled$page As Byte , Byval Oled$col As Byte)
Local Oled$page_adr As Byte , Oled$col_adr1 As Byte , Oled$col_adr2 As Byte

   Oled$page_adr = Oled$page And &B00000111       'convert page address into "Set Page Address" command
   Oled$page_adr = Oled$page_adr Or &B10110000
   Oled$col_adr2 = Oled$col And &B01111111       'convert column address into lower and higher address bits
   Oled$col_adr2 = Oled$col + 2
   Oled$col_adr1 = Oled$col_adr2 And &B11110000
   Swap Oled$col_adr1
   Oled$col_adr1 = Oled$col_adr1 Or &B00010000       'format "send 4 higher address bits" command
   Oled$col_adr2 = Oled$col_adr2 And &B00001111       'format "send 4 lower address bits" command

   I2cstart                   'start condition
   I2cwbyte Oled$addr_w       'OLED write address
   I2cwbyte &B10000000        'next byte is a command byte
   I2cwbyte Oled$page_adr     'send page address
   I2cwbyte &B10000000        'next byte is a command byte
   I2cwbyte Oled$col_adr1     'send 4 higher column address bits
   I2cwbyte &B10000000        'next byte is a command byte
   I2cwbyte Oled$col_adr2     'send 4 lower column address bits

End Sub