GLCD 192x64

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
Mast
Posts: 65
Joined: Wed Aug 29, 2007 6:24 am
Location: France

GLCD 192x64

Post by Mast » Wed Aug 29, 2007 6:29 am

Hi all,
i have a problem with my 192x64. This is my KS0108.bas with CS3. That work fine only if : Line (128,0,191,0). If the line is (128,0,191,63), i have three lines. Where is the problem. Thanks

{
****************************************************************
* Name : KS0108.BAS *
* Author : David John Barker *
* Notice : Copyright (c) 2006 Mecanique *
* : All Rights Reserved *
* Date : 02/05/2006 *
* Version : 1.0 *
* Notes : *
* : *
****************************************************************
}
Module KS0108

// 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 = PORTD // data port
#option GLCD_RS = PORTB.2 // RS pin
#option GLCD_RST =PORTB.5
#option GLCD_EN = PORTB.4 // EN pin
#option GLCD_RW = PORTB.3 // RW pin c0
#option GLCD_CS1 = PORTB.0 // chip select E1
#option GLCD_CS2 = PORTB.1 // chip select E2
#option GLCD_CS3 = PORTB.6 // chip select E2
#option GLCD_ASPECT_RATIO = 75 // aspect ratio, smaller number will squeeze y for GLCD circles and box
#option GLCD_INIT_DELAY = 1000 // initialisation delay (ms)
#option GLCD_INVERT_CS = false // invert CS lines... false

// 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

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

// validate EN pin...
#if IsOption(GLCD_EN) And Not IsValidPortPin(GLCD_EN)
#error GLCD_EN, "Invalid option. EN must be a valid port pin."
#endif

// validate RW pin...
#if IsOption(GLCD_RW) And Not IsValidPortPin(GLCD_RW)
#error GLCD_RW, "Invalid option. RW must be a valid port pin."
#endif

// validate CS1 pin...
#if IsOption(GLCD_CS1) And Not IsValidPortPin(GLCD_CS1)
#error GLCD_CS1, "Invalid option. CS1 must be a valid port pin."
#endif

// validate CS2 pin...
#if IsOption(GLCD_CS2) And Not IsValidPortPin(GLCD_CS2)
#error GLCD_CS2, "Invalid option. CS2 must be a valid port pin."
#endif

// validate CS3 pin...
#if IsOption(GLCD_CS3) And Not IsValidPortPin(GLCD_CS3)
#error GLCD_CS3, "Invalid option. CS3 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

// validate invert CS...
#if IsOption(GLCD_INVERT_CS)
#if Not (GLCD_INVERT_CS in (true, false))
#error GLCD_INVERT_CS, "Invalid option. GLCD invert CS must be true or false."
#endif
#endif

// validate RST pin...
#if IsOption(GLCD_RST) And Not IsValidPortPin(GLCD_RST)
#error GLCD_RST, "Invalid option. RST must be a valid port pin."
#endif

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

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

// x, y position...
Public Dim
Pos As TPosition

// KS0108 commands...
Const
cmdOn = $3F,
cmdOff = $3E,
cmdPage = $B8, '$B8
cmdColumn = $40,
cmdRam = $C0,
GLCDDelay = GLCD_INIT_DELAY

// port and pin settings, these are brought into
// the program by using the above options...
Dim
DATA As GLCD_DATA, // data in (PORT)
TRISData As _GLCD_DATA_TRIS, // data TRIS
RS As GLCD_RS.GLCD_RS@, // RS pin (instruction or data)
EN As GLCD_EN.GLCD_EN@, // EN pin
RW As GLCD_RW.GLCD_RW@, // RW pin (read or write)
CS1 As GLCD_CS1.GLCD_CS1@, // chip1 select
CS2 As GLCD_CS2.GLCD_CS2@, // chip2 select

// ------------------------------------------------------
CS3 As GLCD_CS3.GLCD_CS3@ // chip3 select
// ------------------------------------------------------

#if IsOption(GLCD_RST)
Dim
RST As GLCD_RST.GLCD_RST@ // RST pin
#endif
{
****************************************************************************
* Name : CheckPage (PRIVATE) *
* Purpose : Toggles between left and right half of GLCD *
****************************************************************************
}
Sub CheckPage()

If Pos.x <= 63 Then
CS1 = 0
CS2 = 1
CS3 = 1
EndIf

If Pos.x > 63 And Pos.x <= 127 Then
CS1 = 1
CS2 = 0
CS3 = 1
EndIf

If Pos.x > 127 Then
CS1 = 1
CS2 = 1
CS3 = 0
EndIf

End Sub


{
****************************************************************************
* Name : StrobeEN (PRIVATE) *
* Purpose : Strobe the GLCD EN pin *
****************************************************************************
}
Inline Sub StrobeEN()
EN = 1
DelayUS(1)
EN = 0
End Sub
{
****************************************************************************
* Name : GLCDData (PRIVATE) *
* Purpose : Switch to GLCD data mode *
****************************************************************************
}
Inline Sub GLCDData()
RS = 1
End Sub
{
****************************************************************************
* Name : GLCDInst (PRIVATE) *
* Purpose : Switch to GLCD instruction mode *
****************************************************************************
}
Inline Sub GLCDInst()
RS = 0
End Sub
{
****************************************************************************
* Name : GLCDRead (PRIVATE) *
* Purpose : Set GLCD to read mode *
****************************************************************************
}
Inline Sub GLCDRead()
RW = 1
End Sub
{
****************************************************************************
* Name : GLCDWrite (PRIVATE) *
* Purpose : Set GLCD to write mode *
****************************************************************************
}
Inline Sub GLCDWrite()
RW = 0
End Sub
{
****************************************************************************
* Name : WaitForIdle (PRIVATE) *
* Purpose : Block further GLCD access until signalled ready. *
****************************************************************************
}
Sub WaitForIdle()
Dim Timeout As Byte
Timeout = $FF
GLCDInst // instruction data
GLCDRead // read mode
TRISData = $FF // set data bus to input
Repeat
ClrWDT
StrobeEN
Dec(Timeout)
Until (DATA.7 = 0) Or (Timeout = 0)
End Sub
{
****************************************************************************
* Name : SetData (PRIVATE) *
* Purpose : Write a data byte to GLCD *
****************************************************************************
}
Sub SetData(pData As Byte)
WaitForIdle // block until not busy
GLCDData // access display RAM data
GLCDWrite // write mode
TRISData = $00 // set data bus to output
DATA = pData // write to the bus
StrobeEN // write to GLCD
End Sub
{
****************************************************************************
* Name : GetData (PRIVATE) *
* Purpose : Read byte from GLCD *
****************************************************************************
}
Function GetData() As Byte
WaitForIdle // block until not busy
TRISData = $FF // set data bus to input
GLCDData // access display RAM data
GLCDRead // read mode
StrobeEN // latch data
Result = DATA // get the data
End Function
{
****************************************************************************
* Name : Command (PRIVATE) *
* Purpose : Write a command byte to GLCD *
****************************************************************************
}
Sub Command(pCommand As Byte)
WaitForIdle // block until not busy
GLCDInst // instruction mode
GLCDWrite // write mode
TRISData = $00 // set data bus to output
DATA = pCommand // write to the bus
StrobeEN // write to GLCD
End Sub
{
****************************************************************************
* Name : SetPosition (PRIVATE) *
* Purpose : Set GLCD x and y positions *
****************************************************************************
}
Sub SetPosition()
CheckPage // set correct page
Command(cmdColumn Or Pos.x) // set x position
Command(cmdPage Or Pos.y) // set y position
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

// enable both displays...
'#if GLCD_INVERT_CS
'CS1 = 1
'CS2 = 1
'CS3 = 1
'#else
CS1 = 0
CS2 = 0
CS3 = 0
'#endif
Command(cmdOff)
y = 0
Repeat
Command(cmdPage Or y)
x = 0
Repeat
Command(cmdColumn Or x)
SetData($00)
Inc(x)
Until x > 192 ' 63
Inc(y)
Until y > 7
Command(cmdRam)
Command(cmdOn)
End Sub
{
****************************************************************************
* Name : Initialize *
* Purpose : Configure the GLCD before use *
****************************************************************************
}
Sub Initialize()
#if IsOption(GLCD_RST)
Output(RST)
RST = 1
#endif
Pos.x = 0
Pos.y = 0
DelayMS(GLCDDelay) // start up delay, allow GLCD to settle
Output(EN) // enable is low
Output(RS) // data or instruction is low (command mode)
Output(RW) // read/write is low
Output(CS1) // screen (1)
Output(CS2) // screen (2)
Output(CS3) // screen (3)
Command(cmdRam)
Command(cmdOn)
End Sub

// configure the module
Initialize

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Wed Aug 29, 2007 7:49 am

Try changing the SetPosition sub to:

Code: Select all

Sub SetPosition()
   Dim xPos As Byte
   CheckPage                   // set correct page
   xPos = Pos.x
   If xPos > 63 Then           // find x position for left, middle or right controller
      xPos = xPos - 64
   EndIf
   If xPos > 63 Then
      xPos = xPos - 64
   EndIf
   Command(cmdColumn Or xPos)  // set x position	
   Command(cmdPage Or Pos.y)   // set y position
End Sub
Since the x co-ordinate is now larger, when OR'ed with cmdColumn, it will go over the 6 LSB that it would have stayed within before. The sub above re-calculates the xPos in each page of the display.

Otherwise, your changes look good, but I would allow for the GLCD_Invert again if you can. It would be good to post this on the wiki if you get it working.

Regards,

Steve

User avatar
octal
Registered User
Registered User
Posts: 586
Joined: Thu Jan 11, 2007 12:49 pm
Location: Paris IDF
Contact:

Post by octal » Wed Aug 29, 2007 8:09 am

Hi Steven ...
I agree with your remarks ... The K0108 controller always (all I have seen) use blocks with 64 pixels wide. So I think that the code of the driver has to be a bit reworked to use exclusively constants relative to screen width ... and height (instead of x<128 ....) .

Regards
Octal

Mast
Posts: 65
Joined: Wed Aug 29, 2007 6:24 am
Location: France

Post by Mast » Wed Aug 29, 2007 9:07 am

Thank you Steven. I change llok and post it.

Regards
Mast

User avatar
octal
Registered User
Registered User
Posts: 586
Joined: Thu Jan 11, 2007 12:49 pm
Location: Paris IDF
Contact:

Post by octal » Thu Aug 30, 2007 5:38 am

Hi Steven. I rewrote the SetPosition sub and it seems to work fine

Code: Select all

Sub SetPosition()
   Dim xPos As Byte
   CheckPage                   // set correct page
   xPos = Pos.x
   xPos = xPos Mod 64   '<<<< to replace the two IFs
   Command(cmdColumn Or xPos)  // set x position   
   Command(cmdPage Or Pos.y)   // set y position
End Sub 

Is there any reason (size code or execution performance) for writing it using two IF-THEN tests ?

BTW. The module is working very fine Mast and me are testing it on physical glcd. All pixels are accessible and all Swordfish graphics functions and fonts are working fine. Before publishing it, I'll try to reuse part of the code Steven gave me yesturday(for CS3 management, Thanks Steven) in order to make a unique (generic) module that can handle screens with two or three CS pins. The additions I want to add is to add options that indicates the size of each bloc since I have seen yesturday on another forum users complains from some screens having 120 pixels width and blocks of 60 pixel width instead of 64.
I'll post everything on the WIKI once the module ready and fully tested (this weekend I hope).

A nice photo of the glcd 192x64 pixels :) (each screen rectangle on the image is 64 pixels wide)
Image
Regards
Octal

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Thu Aug 30, 2007 7:18 am

Excellent! All seems to be working well. The replacement of the if-thens with the mod is clever - I hadn't thought of that one, but provided that it compiles smaller, it's a good improvement. Also, you could just do:

Code: Select all

Sub SetPosition() 
   Dim xPos As Byte 
   CheckPage                   // set correct page 
   xPos = Pos.x Mod 64
   Command(cmdColumn Or xPos)  // set x position    
   Command(cmdPage Or Pos.y)   // set y position 
End Sub
Small changes here will help, as this sub will be called many times when writing to the display.
Thanks for offering to tidy up and post your changes to the module.

Steve

Post Reply