SSD1306 OLED controller support

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

Post Reply
skartalov
Posts: 37
Joined: Fri Apr 09, 2010 10:50 am
Location: BULGARIA

SSD1306 OLED controller support

Post by skartalov » Thu Mar 07, 2013 7:21 am

Hi,
after few days trying, polishing, testing.... the code found in article in digital-diy.com forum, I suceed to run this little beautiful OLED graphic display 128x64 pixels, with SSD1306 controller, available in ebay for 5-6 USD.

I am sharing the working code with you, hoping that someone will put effort to incorporate this into GLCD.BAS, so the display become available to all.

Image

Code: Select all

Program MINI_LCD

Device = 18F2520
Clock = 20

Dim    oledWR         As PORTC.0
Dim    oledRD         As PORTC.1 
Dim    oledCS         As PORTC.4 
Dim    oledRESET      As PORTC.2
Dim    oledD_C         As PORTC.3

Dim     oledRESET_TRIS   As TRISC.2
Dim    oledCS_TRIS      As TRISC.4
Dim    oledRD_TRIS      As TRISC.1
Dim    oledWR_TRIS      As TRISC.0
Dim    oledD_C_TRIS   As TRISC.3

Dim     oledBus_TRIS    As TRISB                            
Dim     oledBus         As LATB
Dim     oledBus_PORT    As PORTB


Dim     count As Word

Const   OFFSET = 2
Const   SCREEN_HOR_SIZE = 128
Const   SCREEN_VER_SIZE = 64


// OLED font 8x6 pixels
Public Const _font8x6() As Byte = 
(

     $00, $00, $00, $00, $00, $00 , // " " $20
     $00, $00, $4f, $00, $00, $00 , // !   $21
     $00, $07, $00, $07, $00, $00 , // "   $22
     $14, $7f, $14, $7f, $14, $00 , // #   $23
     $24, $2a, $7f, $2a, $12, $00 , // $   $24
     $23, $13, $08, $64, $62, $00 , // %   $25
     $36, $49, $55, $22, $50, $00 , // &   $26
     $00, $05, $03, $00, $00, $00 , // '   $27
     $00, $1c, $22, $41, $00, $00 , // (   $28
     $00, $41, $22, $1c, $00, $00 , // )   $29
     $14, $08, $3e, $08, $14, $00 , // *   $2A
     $08, $08, $3e, $08, $08, $00 , // +   $2B
     $00, $50, $30, $00, $00, $00 , // ,   $2C
     $08, $08, $08, $08, $08, $00 , // -   $2D
     $00, $60, $60, $00, $00, $00 , // .   $2E
     $20, $10, $08, $04, $02, $00 , // /   $2F
     $3e, $51, $49, $45, $3e, $00 , // 0   $30
     $00, $42, $7f, $40, $00, $00 , // 1   $31
     $42, $61, $51, $49, $46, $00 , // 2   $32
     $21, $41, $45, $4b, $31, $00 , // 3   $33
     $18, $14, $12, $7f, $10, $00 , // 4   $34
     $27, $45, $45, $45, $39, $00 , // 5   $35
     $3c, $4a, $49, $49, $30, $00 , // 6   $36
     $01, $71, $09, $05, $03, $00 , // 7   $37
     $36, $49, $49, $49, $36, $00 , // 8   $38
     $06, $49, $49, $29, $1e, $00 , // 9   $39
     $00, $36, $36, $00, $00, $00 , // :   $3A
     $00, $56, $36, $00, $00, $00 , // ;   $3B
     $08, $14, $22, $41, $00, $00 , // <   $3C
     $14, $14, $14, $14, $14, $00 , // =   $3D
     $00, $41, $22, $14, $08, $00 , // >   $3E
     $02, $01, $51, $09, $06, $00 , // ?   $3F
     $32, $49, $79, $41, $3e, $00 , // @   $40
     $7e, $11, $11, $11, $7e, $00 , // A   $41
     $7f, $49, $49, $49, $36, $00 , // B   $42
     $3e, $41, $41, $41, $22, $00 , // C   $43
     $7f, $41, $41, $22, $1c, $00 , // D   $44
     $7f, $49, $49, $49, $41, $00 , // E   $45
     $7f, $09, $09, $09, $01, $00 , // F   $46
     $3e, $41, $49, $49, $7a, $00 , // G   $47
     $7f, $08, $08, $08, $7f, $00 , // H   $48
     $00, $41, $7f, $41, $00, $00 , // I   $49
     $20, $40, $41, $3f, $01, $00 , // J   $4A
     $7f, $08, $14, $22, $41, $00 , // K   $4B
     $7f, $40, $40, $40, $40, $00 , // L   $4C
     $7f, $02, $0c, $02, $7f, $00 , // M   $4D
     $7f, $04, $08, $10, $7f, $00 , // N   $4E
     $3e, $41, $41, $41, $3e, $00 , // O   $4F
     $7f, $09, $09, $09, $06, $00 , // P   $50
     $3e, $41, $51, $21, $5e, $00 , // Q   $51
     $7f, $09, $19, $29, $46, $00 , // R   $52
     $46, $49, $49, $49, $31, $00 , // S   $53
     $01, $01, $7f, $01, $01, $00 , // T   $54
     $3f, $40, $40, $40, $3f, $00 , // U   $55
     $1f, $20, $40, $20, $1f, $00 , // V   $56
     $3f, $40, $38, $40, $3f, $00 , // W   $57
     $63, $14, $08, $14, $63, $00 , // X   $58
     $07, $08, $70, $08, $07, $00 , // Y   $59
     $61, $51, $49, $45, $43, $00 , // Z   $5A
     $00, $7f, $41, $41, $00, $00 , // [   $5B
     $02, $04, $08, $10, $20, $00 , // "\" $5C
     $00, $41, $41, $7f, $00, $00 , // ]   $5D
     $04, $02, $01, $02, $04, $00 , // ^   $5E
     $40, $40, $40, $40, $40, $00 , // _   $5F
     $00, $01, $02, $04, $00, $00 , // `   $60
     $20, $54, $54, $54, $78, $00 , // a   $61
     $7f, $48, $44, $44, $38, $00 , // b   $62
     $38, $44, $44, $44, $20, $00 , // c   $63
     $38, $44, $44, $48, $7f, $00 , // d   $64
     $38, $54, $54, $54, $18, $00 , // e   $65
     $08, $7e, $09, $01, $02, $00 , // f   $66
     $0c, $52, $52, $52, $3e, $00 , // g   $67
     $7f, $08, $04, $04, $78, $00 , // h   $68
     $00, $44, $7d, $40, $00, $00 , // i   $69
     $20, $40, $44, $3d, $00, $00 , // j   $6A
     $7f, $10, $28, $44, $00, $00 , // k   $6B
     $00, $41, $7f, $40, $00, $00 , // l   $6C
     $7c, $04, $18, $04, $78, $00 , // m   $6D
     $7c, $08, $04, $04, $78, $00 , // n   $6E
     $38, $44, $44, $44, $38, $00 , // o   $6F
     $7c, $14, $14, $14, $08, $00 , // p   $70
     $08, $14, $14, $18, $7c, $00 , // q   $71
     $7c, $08, $04, $04, $08, $00 , // r   $72
     $48, $54, $54, $54, $20, $00 , // s   $73
     $04, $3f, $44, $40, $20, $00 , // t   $74
     $3c, $40, $40, $20, $7c, $00 , // u   $75
     $1c, $20, $40, $20, $1c, $00 , // v   $76
     $3c, $40, $30, $40, $3c, $00 , // w   $77
     $44, $28, $10, $28, $44, $00 , // x   $78
     $0c, $50, $50, $50, $3c, $00 , // y   $79
     $44, $64, $54, $4c, $44, $00 , // z   $7A
     $00, $08, $36, $41, $00, $00 , // {   $7B
     $00, $00, $7f, $00, $00, $00 , // |   $7C
     $00, $41, $36, $08, $00, $00 , // }   $7D
     $02, $01, $02, $04, $02, $00 , // ~   $7E
     $00, $00, $00, $00, $00, $00 , // -- filler --
    //----------------------------------------------------------//
    //  custom characters, mostly unuseful                      //
    //----------------------------------------------------------//
   
     $00, $7f, $45, $45, $45, $47 , //     $80 - left half of folder
     $44, $44, $44, $44, $7c, $00  //     $81 - right half of folder
)

Include "Convert.bas"
Include "string.bas"

Public Sub Nop()

 ASM
    Nop
 End ASM 
 
End Sub

{*********************************************************************
* Function:  WriteCommand()
* Overview: Writes command Word To the display controller. A delay
*         is inserted at the End To meet the controller requirements
*         on selected commands.
* Input: Command Byte To send To Device
* Output: none
********************************************************************}
Public Sub WriteCommand(cmd As Byte)

    oledBus_TRIS =      %00000000
    oledBus      =      cmd     // data on bus
    oledRD = 1         // set RD
    oledWR = 1         // set WR
    oledD_C   = 0        // clear DC(A0)
    oledCS = 0         // clear CS (select device)
    oledWR = 0         // clear WR (clock WR)
    Nop()
    oledWR = 1         // set WR (clock WR)
    oledCS = 1         // set CS (
    oledBus_TRIS = $FF
    
End Sub

{*********************************************************************
* Function: WriteData()
* Overview: Writes data word to the display controller. A delay
*         is inserted at the end to meet the controller requirements
*         on selected commands.
* Input: Data byte to send to device
* Output: none
********************************************************************}
Public Sub WriteData( data As Byte)

    oledBus_TRIS = $00
    oledBus  = data
    oledRD = 1
    oledWR = 1
    oledD_C   = 1
    oledCS = 0
    oledWR = 0
    Nop()
    oledWR = 1
    oledCS = 1
    oledBus_TRIS = $FF
    
End Sub

Public Sub SetAddress(page As Byte, lowerAddr As Byte, higherAddr As Byte)
   WriteCommand(page)
   WriteCommand(lowerAddr)
   WriteCommand(higherAddr)
End Sub


{*********************************************************************
* Function: FillDisplay()
* Overview: Fill the display with data. Use this to clear or set all
*           display. 
* Input: $ff(white display) or $00(clear display)
* Output: none
********************************************************************}
Public Sub FillDisplay(data As Byte)

    Dim page As Byte
    Dim col As Byte

    For Page = $B0 To $B8
        SetAddress(page, $00+OFFSET, $10)
        For col = 0 To SCREEN_HOR_SIZE - 1
            WriteData(data)
        Next
    Next
   
End Sub


{*********************************************************************
* Function:  void ResetDevice()
* Input: none
* Output: none
* Overview: resets And initialize OLED
********************************************************************}
Public Sub ResetDevice()

    Dim i As Byte   
    // Configure control pins
    oledRESET_TRIS = 0
    oledWR = 0
    oledWR_TRIS = 0
    oledRD = 0
    oledRD_TRIS = 0
    oledCS = 1
    oledCS_TRIS = 0
    oledD_C   = 0
    oledD_C_TRIS = 0

    //Reset the device
    oledRESET = 0
    For i = 1 To 100
    Next 
    oledRESET = 1
    For i = 1 To 100
    Next 


    // Setup Display
    WriteCommand($ae)             
    WriteCommand($d5)                   
    WriteCommand($80)
    
     // Multiplex Ratio
    WriteCommand($a8)             
    WriteCommand($3f)              
    
    // Display Offset
    WriteCommand($d3)             
    WriteCommand($00)              
   
    // Display Start Line
    WriteCommand($40)           
    
    // Set Charge Pump
    WriteCommand($8d)
    WriteCommand($14)           
    
    // Re-map
    WriteCommand($a1)             
    
    // COM Output Scan Direction
    WriteCommand($c8)            
    
    // COM Pins Hardware Configuration
    WriteCommand($da)             
    WriteCommand($12)              

     // Contrast Control Register
    WriteCommand($81)           
    WriteCommand($cf)           // $9f - External, $CF - Internal   

    // Set Pre Charge Period
    WriteCommand($d9)
    WriteCommand($F1)           // $22 - External, $F1 - Internal
    
    // Set VCOMH Deselect level
    WriteCommand($db)
    WriteCommand($40)
    
    // Display OFF
    WriteCommand($a4)         
    
   //Normal or Inverse Display
   WriteCommand($a6)             // Normal display
    
    
    // Display ON
    WriteCommand($af)
   
   //DelayMS(10)

End Sub


Public Sub oledWriteChar1x(letter As Char, page As Byte, column As Byte, invert As Boolean)

   Dim b, i As Byte
   Dim ix   As Word

                                                            
   WriteCommand(page)
   column = column + OFFSET
   WriteCommand($00 + (column And $0F))
   WriteCommand($10+((column>>4)And $0F))

   ix = (StrToDec(letter) - StrToDec(" ")) * 6
   For i = 0 To 5
      b = _font8x6(ix + i)
      If (invert) Then
         b = Not(b)
      EndIf
      WriteData(b)
   Next
   
End Sub




{*********************************************************************
* Function: oledPutROMStringInvertOption()
* Overview: Prints ROM stored strings.           
* Input: pointer to ROM stored string, page, column and invert option
* Output: print the string on OLED
********************************************************************}
Public Sub oledPutROMStringInvertOption(ByRefConst RomString() As Byte, page As Byte, column As Byte, invert As Boolean)

   Dim  i, x As Byte
   
   If((page>=0) And (page<8))
   Then   
       i=column
       page = page + $B0
       //While(romstring())
       For  x = 0 To Bound(RomString())     
             oledWriteChar1x(romstring(x), page, i, invert)
             //inc(ptr)
          i=i+6
         //Wend
        Next        
   End If
End Sub




{*********************************************************************
* Function: oledPutImage()
* Overview: Puts on display ROM stored images.            
* Input: pointer to ROM stored image array,
* Output: 
********************************************************************}
Public Sub oledPutImage( ByRefConst RomString() As Byte,  sizex As Byte, sizey As Byte, startx As Byte, starty As Byte)

   Dim i, j, mask As Byte
   Dim count As Integer
   
   count=0
   startx = startx + OFFSET
   
   For i = $B0+starty To $B0+sizey
      WriteCommand(i)
      WriteCommand(startx And $0F)
      WriteCommand($10 Or ((startx>>4) And $0F))
     
      For j = 0 To sizex
         Inc(count)
        
         WriteData(Romstring(j+1))
      Next 
   Next 
End Sub

Public Sub oledWriteChar1x(letter As Byte, page As Byte, column As Byte, invert As Boolean)

    Dim b, i As Byte
    Dim ix   As Word

    ix = (letter - Byte(" ")) * 6       // Adjust character to table that starts at $20
    For i = 0 To 5
        b = _font8x6(ix + i)
        If (invert) Then
            b = Not(b)
        EndIf
        WriteData(b)
    Next
       
End Sub


Public Sub oledPutString(text As String, page As Byte, column As Byte, invert As Boolean = false)

    Dim  i, x As Byte
       
    If ((page>=0) And (page<8)) Then   
        i = column
        page = page + $B0
        x = 0
        While(Byte(text(x))<>0)
            oledWriteChar1x(text(x), page, i, invert)
            Inc(x)
            i = i+6
        Wend
    End If
End Sub
     
main:
    ADCON1 = $0f
    TRISA=0
    LATA =0
    DelayMS(10)
    ResetDevice()

    FillDisplay($FF)
    DelayMS(200)
    FillDisplay($00)
    
    
    oledPutString("Line 1",0,0)
    oledPutString("Line 2",1,0,TRUE)
    oledPutString("Line 3",2,0)
    oledPutString("Line 4",3,0,TRUE)
    oledPutString("Line 5",4,0)
    oledPutString("Line 6",5,0,TRUE)
    oledPutString("Line 7",6,0)
    oledPutString("Line 8",7,0,TRUE)
    DelayMS(1500)
    count=0
    FillDisplay(0)
    oledPutString("Count: ",0,0)
    oledPutString("TEST PROG",7,0)
While true
    Inc(count)
    oledPutString(DecToStr(count),1,60)
    delayms(100)
Wend

User avatar
ohararp
Posts: 194
Joined: Tue Oct 03, 2006 11:29 pm
Location: Dayton, OH USA
Contact:

Post by ohararp » Sat Mar 09, 2013 4:27 pm

Great looking project! Im interested to learn more about your navigation device. Is that custom button?
Thanks Ryan
$25 SMT Stencils!!!
www.ohararp.com/Stencils.html

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Sat Mar 09, 2013 6:10 pm

> Great looking project

I agree, thanks for sharing...

Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Sat Mar 09, 2013 8:20 pm

Funny, I just used one of those myself. Its a C&K TSW series switch.

http://www.ck-components.com/tsw/naviga ... 51,en.html

In the States you can get them at Mouser or Digikey.

I'd be interested in what/how it was being used.

User avatar
ohararp
Posts: 194
Joined: Tue Oct 03, 2006 11:29 pm
Location: Dayton, OH USA
Contact:

Post by ohararp » Sat Mar 09, 2013 8:28 pm

Thanks Ryan
$25 SMT Stencils!!!
www.ohararp.com/Stencils.html

skartalov
Posts: 37
Joined: Fri Apr 09, 2010 10:50 am
Location: BULGARIA

Post by skartalov » Sun Mar 10, 2013 10:54 am

Jerry Messina wrote:I'd be interested in what/how it was being used.
This rotary switch (Brand ZIPPY) is very useful indeed.
It has 5 buttons - left, right, up, down and center with common pinout
+ rotary switch with approx.20 pos/rev .
I wonder where I can find library part for EAGLE PCB?

Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Sun Mar 10, 2013 11:11 am

The C&K part is identical, so they're likely the same part.

I was limited on what pins I could connect to it, so I ended up just polling the scroll wheel encoder. What method did you use?

skartalov
Posts: 37
Joined: Fri Apr 09, 2010 10:50 am
Location: BULGARIA

Post by skartalov » Sun Mar 10, 2013 4:20 pm

I connect this on PORTB using the internal pull ups.
I have sub routine that reads the rotary switches and detects motion, then return byte variable, which contains the direction of rotation.

skartalov
Posts: 37
Joined: Fri Apr 09, 2010 10:50 am
Location: BULGARIA

Post by skartalov » Wed Mar 13, 2013 3:24 pm

This is the final design of the device!

Hope you like it.

And best of all -> It is powered by SWORDFISH :-)

Image

Jon Chandler
Registered User
Registered User
Posts: 185
Joined: Mon Mar 10, 2008 8:20 am
Location: Seattle, WA USA
Contact:

Post by Jon Chandler » Wed Mar 13, 2013 8:15 pm

Awesome job! The enclosure and encoder look sweet.
Jon

Check out the TAP-28 PIC Application board at http://www.clever4hire.com/throwawaypic/

skartalov
Posts: 37
Joined: Fri Apr 09, 2010 10:50 am
Location: BULGARIA

GLCD support for OLED SSD1306

Post by skartalov » Wed Apr 03, 2013 12:39 pm

As I don't know exactly how to post to WIKI, I will ask someone to do so!
------------------


I am finally ready for integrate this SSD1306 OLED controller into SWORDFISH. It uses 8080 Mode, parallel interface, with RD and WR signals.

So here it goes:

Add this to your GLCD.BAS:

Code: Select all

// import ssd1306 driver...
#IF GLCD_MODEL = SSD1306
Include "SSD1306.bas"                
Public Dim
   Pos As SSD1306.Pos, 
   Cls As SSD1306.Cls,
   SetPixel As SSD1306.SetPixel,
   WriteByte As SSD1306.WriteByte,
   ReadByte As SSD1306.ReadByte,
   GetPixel As SSD1306.GetPixel,
   InitOLED As SSD1306.InitOLED
#ENDIF
Don't forget to include the new driver into the glcd.bas option list:

Code: Select all

// validate model...
#option GLCD_MODEL = SSD1306
#IF Not (GLCD_MODEL in (KS0108, S1D10605, S1D15G00, SED1520, S1D13700, KS0713, SSD1306,ST7565))
   #ERROR GLCD_MODEL, "Invalid option. GLCD model not recognized."
#ENDIF
then create a program named "SSD1306.bas" and save it to your user library folder:

Code: Select all

Module SSD1306
// import the graphics module...
#define GLCD_PIXEL_01
#define GLCD_COLOR_01
#define GLCD_XY_08
Include "Graphics.bas"   
Include "system.bas"   

// default module options - user options can override these values...
#option GLCD_DATA = PORTC        // data port
#option GLCD_RS = PORTA.1        // RESET pin
#option GLCD_WR = PORTA.3        // 
#option GLCD_RD = PORTA.4        // 
#option GLCD_CS = PORTA.0       // chip select
#option GLCD_DC = PORTA.2
#option GLCD_ASPECT_RATIO = 100   // aspect ratio, smaller number will squeeze y for GLCD circles and box
#option GLCD_INIT_DELAY = 100    // initialisation delay (ms)

// validate data port...
#if IsOption(GLCD_DATA) 
   #if Not IsValidPort(GLCD_DATA)
      #error GLCD_DATA, "Invalid option. DATA must be a valid port name."
   #endif
   #ifdef GLCD_DATA@ Then
      #error GLCD_DATA@, "Invalid option. DATA port cannot be a single bit value."
   #endif
#endif

#if IsOption(GLCD_RS) And Not IsValidPortPin(GLCD_RS) 
   #error GLCD_RS, "Invalid option. RS must be a valid port pin."
#endif

#if IsOption(GLCD_WR) And Not IsValidPortPin(GLCD_WR) 
   #error GLCD_WR, "Invalid option. WR must be a valid port pin."
#endif

#if IsOption(GLCD_RD) And Not IsValidPortPin(GLCD_RD) 
   #error GLCD_RD, "Invalid option. RD must be a valid port pin."
#endif

#if IsOption(GLCD_CS) And Not IsValidPortPin(GLCD_CS) 
   #error GLCD_CS, "Invalid option. CS must be a valid port pin."
#endif

#if IsOption(GLCD_DC) And Not IsValidPortPin(GLCD_DC) 
   #error GLCD_DC, "Invalid option. DC must be a valid port pin."
#endif

// validate initialisation delay...
#if IsOption(GLCD_INIT_DELAY)
   #if Not (GLCD_INIT_DELAY in (0 to 1000))
      #error GLCD_INIT_DELAY, "Invalid option. GLCD initialize delay must be between 0 and 1000 (ms)."
   #endif
#endif 

// now create Data TRIS...
#option _GLCD_DATA_TRIS = GetTRIS(GLCD_DATA)

// GLCD width and height...
Public Const
   GLCDWidth = 128,
   GLCDHeight = 64

// x, y position...
Public Dim
   Pos As TPosition
  
Const
   cmdPage = $B0,
   GLCDDelay = GLCD_INIT_DELAY     

// port and pin settings, these are brought into
// the program by using the above options...
Dim        
   DATA As GLCD_DATA,           
   TRISData As _GLCD_DATA_TRIS, 
   RS As GLCD_RS.GLCD_RS@,      
   RD As GLCD_RD.GLCD_RD@,     
   WR As GLCD_WR.GLCD_WR@,      
   CS As GLCD_CS.GLCD_CS@,   
   DC As GLCD_DC.GLCD_DC@    

{
****************************************************************************
* Name    : WaitForIdle (PRIVATE)                                          *
* Purpose : Block further GLCD access until signalled ready.               *
****************************************************************************
}     
Sub WaitForIdle()
   'DelayUS(1)
End Sub 
{
****************************************************************************
* Name    : SetData (PRIVATE)                                              *
* Purpose : Write a data byte to GLCD                                      *
****************************************************************************
}     
Sub SetData(pData As Byte) 
   WaitForIdle
   TRISData=$00
   DATA = pData
   DC=1
   CS=0            
   WR=0
   'DelayUS(1)
   WR=1
   CS=1
End Sub
{
****************************************************************************
* Name    : GetData (PRIVATE)                                              *
* Purpose : Read byte from GLCD                                            *
****************************************************************************
}     
Function GetData() As Byte
   WaitForIdle      
   TRISData = $FF   
   DC=1
   CS=0 
   RD=0
   'DelayUS(1)
   RD=1
   Result = DATA    // get the data
   CS=1
End Function  
{
****************************************************************************
* Name    : Command (PRIVATE)                                              *
* Purpose : Write a command byte to GLCD                                   *
****************************************************************************
}     
Sub Command(pCommand As Byte) 
   WaitForIdle
   TRISData=$00           
   DATA = pCommand        
   DC=0
   CS=0                   
   WR=0             
   'DelayUS(1)
   WR=1
   CS=1
End Sub
{
****************************************************************************
* Name    : SetPosition (PRIVATE)                                          *
* Purpose : Set GLCD x and y positions                                     *
****************************************************************************
}     
Sub SetPosition()
   Command(cmdPage Or Pos.y)   // set y position
   Command($00 + (Pos.x And $0F))
   Command($10+((Pos.x>>4)And $0F))	
   
End Sub
{
****************************************************************************
* Name    : WriteByte                                                      *
* Purpose : Write a byte at x, page                                        *
****************************************************************************
} 
Public Sub WriteByte(pValue As Byte)
   SetPosition
   SetData(pValue)
End Sub 
{
****************************************************************************
* Name    : ReadByte                                                       *
* Purpose : Read a byte at x, page                                         *
****************************************************************************
} 
Public Function ReadByte() As Byte
   SetPosition
   GetData
   Result = GetData
End Function
{
****************************************************************************
* Name    : SetPixel                                                       *
* Purpose : Set pixel at pixel location x,y                                *
****************************************************************************
} 
Public Sub SetPixel(pX, pY As Byte)
   Dim YBit As Byte
   Dim Pixel As Byte
   
   If (pX < GLCDWidth) And (pY < GLCDHeight) Then

      YBit = 1 << (pY Mod 8)
      Pos.y = pY / 8
      Pos.x = pX
   
      SetPosition
      GetData
      Pixel = GetData  

           
      // pen is white...
      If Pen.Color = 0 Then
         If Pen.Mode = pmCopy Then
            yBit = Not yBit
            Pixel = Pixel And YBit
         EndIf
   
      // pen is black...
      Else

         // pen copy or merge...
         If Pen.Mode <> pmXOR Then
            Pixel = Pixel Or yBit
      
         // pen XOR
         Else
            If (Pixel And YBit) = 0 Then
               Pixel = Pixel Or yBit
            Else
               yBit = Not yBit
               Pixel = Pixel And YBit
            EndIf      
         EndIf
      EndIf

      SetPosition
      SetData(Pixel)
   EndIf
End Sub
{
****************************************************************************
* Name    : GetPixel                                                       *
* Purpose : Return pixel colour at pixel position x, y                     *
****************************************************************************
}
Public Function GetPixel(pX, pY As Byte) As TColor
   Dim Pixel As Byte
   Pos.y = pY / 8
   Pos.x = pX
   SetPosition
   GetData
   Pixel = GetData >> (pY Mod 8) 
   Result = Pixel.0  
End Function
{
****************************************************************************
* Name    : Cls                                                            *
* Purpose : Clear the GLCD screen                                          *
****************************************************************************
} 
Public Sub Cls()
   Dim x, y As Byte
   For y=$b0 To $b7
    Command(y)
    Command($00)
    Command($10)
    For x=0 To 127
        SetData(0)
    Next
   Next             
End Sub
     
{
****************************************************************************
* Name    : Initialize                                                     *
* Purpose : Configure the OLED before use                                  *
****************************************************************************
} 
Public Sub InitOLED()
   Pos.x = 0
   Pos.y = 0  
   DelayMS(GLCDDelay) 
   Output(RD)         
   Output(RS)         
   Output(WR)         
   Output(CS)        
   Output(DC)
   Low(RS) DelayMS(10) High(RS)
   DelayMS(50)
   RD=1 WR=1 DC=1
 
    Command($ae)             // turn off the display (AF (175)=ON, AE (174) =OFF)
    Command($d5)                   
    Command($80)
     // Multiplex Ratio
    Command($a8)             
    Command($3f)              
    // Display Offset
    Command($d3)             
    Command($00)              
    // Display Start Line
    Command($40)           
    // Set Charge Pump
    Command($8d)
    Command($14)           // $10 - External, $14 - Internal
    // Re-map
    Command($a0)              
    // COM Output Scan Direction
    Command($c0)            
    // COM Pins Hardware Configuration
    Command($da)             
    Command($12)              
     // Contrast Control Register
    Command($81)           
    Command($cf)           // $9f - External, $CF - Internal   
    // Set Pre Charge Period
    Command($d9)
    Command($F1)           // $22 - External, $F1 - Internal
    // Set VCOMH Deselect level
    Command($db)
    Command($40)
    // Display OFF
    Command($a4)         
   //Normal or Inverse Display
   Command($a6)             // Normal display    
   // Display ON
    Command($af)
End Sub 

In the beginning of your program put:

GLCD.InitOLED()

to initialize the OLED. I didn't put in autorun this intentionally, beacause, if you use Internal MCU Osscilator, it will make some problems!

You are ready to go!

Use #OPTION command to assign the OLED pinouts to your interface.

Image

Jon Chandler
Registered User
Registered User
Posts: 185
Joined: Mon Mar 10, 2008 8:20 am
Location: Seattle, WA USA
Contact:

Post by Jon Chandler » Wed Apr 03, 2013 2:08 pm

Nice work and a great result. Thanks for sharing the code.
Jon

Check out the TAP-28 PIC Application board at http://www.clever4hire.com/throwawaypic/

Post Reply