PDA

View Full Version : Old Chestnut ? - 128 x 64 GLCD



Scampy
- 11th June 2015, 23:21
I'm still evaluating options to display info for a revamp of my old Vivarium Controller project, and whilst the tests with an I2C module that piggybacked on the back of a KS0108 GLCD have proved difficult, the other option is to use traditional wiring to the 20 pin header, and with a bit of juggling around I might just be able to free up the extra pins required.

Anyway, I have a MicroElektronica EasyPIC5 board and their 128 x 64 mono (Blue/white) GLCD. Using a 16F877A, 20mhz crystal and their own example HEX program the file loaded and ran through the demo just fine, so I know the hardware works. Now I only have the demo version of Mikro Basic and I can't re-compile the example code for my target PIC and desired OSC speed as it exceeds the limit, so I went hunting for some examples for PBP and came across this - courtesy of Ranjit Diol - (I've changed the LCD pins to match the pinouts of the LCD I have as the original use different ports)



ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM

DEFINE OSC 20
ADCON1 = $0F
clear


'************************************************* ***********************
' IMPORTANT, PLEASE NOTE THE FOLLOWING
'This application assumes you have a 64KBit external eeprom connected
'via I2C. Without that you will only be able to send images directly
'to the LCD display and not be able to store them -- See the readme.txt
'for the Windows GLiPIC interface.
'
'Adjust the PIN assignments as neccessary for your prototype
'This was tested using a 20MHz xtal if you use a different OSC speed
'you may have to make some adjustement in the 'strobe' subroutine.
'************************************************* ***********************




'routine's e_pause constant for other speeds
ADCON1 = 7 'Make all pins digital, you may adjust as needed


lcd_dat VAR PORTD 'LCD bus Pins 7-14 LSB-MSB
scl VAR PORTC.3 'I2C SCL for ext eeprom
sda VAR PORTC.4 'I2C SDA for ext eeprom
in_pin VAR PORTC.7 'Serial input pin
out_pin VAR PORTC.6 'Serial output pin
lcd_e VAR PORTB.4 'Enable pin on LCD
lcd_cd VAR PORTB.2 'Data/Command R/S on LCD
lcd_rw VAR PORTB.3 'Read/Write on LCD
lcd_cs1 VAR PORTB.0 'ChipSelect1 on LCD
lcd_cs2 VAR PORTB.1 'ChipSelect2 on LCD
lcd_rst VAR PORTB.5 'Reset Pin on LCD

'Set pins for output
TRISB.0 = 0
TRISB.1 = 0
TRISB.2 = 0
TRISD = 0
TRISb.0 = 0
TRISb.1 = 0
TRISb.2 = 0
TRISC.3 = 0
TRISC.4 = 0
TRISb.5 = 0

'Constants used
ser_baud CON 84 '9600 baud serout/serin
ctl CON $A0 'EEprom control code
row CON $b8 'LCD page 0
last_row CON $bf 'LCD page 7
col CON $40 'Line byte position 0
last_col CON 63 'Last column (1-64)
first_col CON 0 'First column
max_col CON 128 'Last column (1-127)
max_line CON 8 'Line 8 (based on 1-8)
max_pos CON 64 'Column 64 positon per side (1-64)
cr CON 13 'CR for serout
lf CON 10 'LF for serout
disp_on CON $3f 'LCD Display ON
disp_off CON $3e 'LCD Display OFF
disp_ram CON $c0 'Ram Display 0 (Page 0 at top of display)
blank CON $00 'Blank character
e_pause CON 6 'Pauseus 6 for Strobe routine

'Word variables used
eepaddr VAR WORD
addr VAR WORD

'Arrays used
in_array VAR byte[32]
in_ctl VAR byte[8]

'Byte Variables used
buff_count VAR BYTE 'buffer count
hex_nibble VAR BYTE 'hex nibble from serin
in_ascii VAR BYTE 'ASCII char from serin
buf_cnt VAR BYTE 'buffer counter
byte_pos VAR BYTE 'To keep track of a byte's position
in_byte VAR BYTE 'The incoming byte
tmp VAR BYTE 'Temporary var
index VAR BYTE 'Index for arrays
j VAR BYTE 'General counter
k VAR BYTE 'General counter
line VAR BYTE 'An LCD row
delay VAR BYTE 'Execution delay, used with 'pause'

'Initialize variables
hex_nibble = 0
byte_pos = 0
delay = 10
in_byte = 0
tmp = 0
index = 0


'Reset LCD
lcd_dat = 0 ' Clear PORTD
lcd_cd = 0
lcd_rw = 0
lcd_e = 0
lcd_cs1 = 1
lcd_cs2 = 0
lcd_rst = 1
pause 100 'Let things stabilize
lcd_rst = 0
pause 10 ' Reset LCD
lcd_rst = 1
pause 500


'Jump over subroutines to main program
goto main

' **** (GO)SUB ROUTINES ****

strobe:
lcd_e = 1
pauseus e_pause
lcd_e = 0
return

clearall:
lcd_cd = 0 ' Command mode
lcd_dat = disp_off ' Display Off
gosub strobe
lcd_cs1=1
lcd_cs2=0
for index = 1 to 2
for j = row to last_row
lcd_cd = 0 'Command mode
gosub strobe ' Write the data
lcd_dat = col ' Column address = 0
gosub strobe
lcd_dat = j
gosub strobe
lcd_cd = 1 ' Write mode
for k = first_col to last_col
lcd_dat = blank
gosub strobe
next
next
swap lcd_cs1,lcd_cs2
next

lcd_cs1=0
lcd_cs2=1
lcd_cd=0
lcd_dat=row
gosub strobe
lcd_dat = disp_ram ' Ram Line 0
gosub strobe
lcd_dat=col
gosub strobe
lcd_cs1=1
lcd_cs2=0
lcd_dat=row
gosub strobe
lcd_dat = disp_ram ' Ram Line 0
gosub strobe
lcd_dat=col
gosub strobe
lcd_dat = disp_on 'display on
gosub strobe
lcd_cd = 1 ' Set Data command
lcd_cs1 = 1 ' Left side active
lcd_cs2 = 0

return


init: 'Initialization

lcd_cd = 0 ' Set command mode
lcd_cs1 = 1 ' Left Side on
lcd_cs2 = 0 ' Right Side off
for index = 1 to 2
lcd_dat = disp_off ' Display Off
lcd_dat = disp_ram ' Ram Line 0
gosub strobe ' Write the data
lcd_dat = col ' Y address = 0
gosub strobe
lcd_dat = row ' Page = 0
gosub strobe
lcd_dat = disp_on ' Display On
gosub strobe
swap lcd_cs1,lcd_cs2
next
lcd_cs1=1
lcd_cs2=0


return

'****Place char on LCD Routine *****
'Place byte of data on lcd assumes in_byte, byte_pos and line (line)
'Char position on LCD byte_pos = 0-127 (Horiz), ROW 0-7 (vert)

putbyte:
lcd_dat = in_byte 'Display the byte
gosub strobe
byte_pos=byte_pos+1 'Increment position

'Now do some LCD house cleaning and adjust counters
if byte_pos=max_pos then
lcd_cs1=0
lcd_cs2=1
lcd_cd = 0
lcd_dat = col
gosub strobe
lcd_dat = disp_ram
gosub strobe
lcd_dat = row + line
gosub strobe
lcd_cd = 1
endif
if byte_pos = max_col then 'Check if
line = line + 1 'New Line
if line = max_line then
line = 0
endif
byte_pos = 0 'Reset byte_pos
lcd_cs1=1
lcd_cs2=0
lcd_cd = 0
lcd_dat=col
gosub strobe
lcd_dat = row + line
gosub strobe
lcd_dat = disp_ram
gosub strobe
lcd_cd =1
endif

return

'***** Convert incoming ascii to hex byte Routine *****
find:
Lookdown in_array[index],["0123456789abcdef"],hex_nibble
return


'===============================
' **** BEGIN MAIN PROGRAM ******
'===============================

main:
gosub init ' Initialize LCD
gosub clearall ' Clear all pages
goto term

logo: gosub init ' Initialize LCD
gosub clearall ' Clear all pages



'**** DISPLAY IMAGES IN EXTERNAL 64KBit EEPROM VIA I2C *****

' Load opening screen from eeprom assuming a 64KBit eeprom

byte_pos=0
line =0
for addr = 0 to 8192 'Eight 1kbyte pages of eeprom
I2CREAD sda,scl,ctl,addr,[in_byte]
gosub putbyte

if (addr=1024) OR (addr=2048) OR (addr= 3072) OR (addr=4096) OR (addr=5120) OR (addr=6144) OR (addr=7168) OR (addr=8192) then
pause 4000

gosub init
gosub clearall
endif

if addr=8192 then
addr = 0
endif

next

goto logo 'Continue looping inifitum!

'********************************************

'Terminal Subroutine
term: 'Assumes Home Position

'Setup variables
j=0
index=0
k=0
line=0
addr=0
in_ascii = 0
buff_count = 32
delay = 10
addr = 0
byte_pos = 0

'Get the initial parameters
get_param:
serin2 in_pin,ser_baud,[wait ("*"),STR in_ctl\9]
for index = 0 to 8
Lookdown in_ctl[index],["0123456789abcdef"],hex_nibble
in_ctl[index]=hex_nibble
next
delay = (in_ctl[7]<<4) | in_ctl[8]
buff_count = (in_ctl[1]<<4) | in_ctl[2]
addr.byte1 = (in_ctl[3] <<4) | in_ctl[4]
addr.byte0 = (in_ctl[5] <<4) | in_ctl[6]
buf_cnt = (buff_count - 1)
eepaddr = addr
j=in_ctl[0]
if j = 0 then lcd_loop 'Display directly on LCD
if j = 1 then eep_loop 'Load ext eeprom
if j = 2 then logo 'Display images loop
goto get_param




eep_loop:

serin2 in_pin,ser_baud,[wait ("]"),STR in_array\buff_count] 'Wait for ] and the load in_array

for index = 0 to buf_cnt
'Get char and place in array
Lookdown in_array[index],["0123456789abcdef"],hex_nibble
in_array[index]=hex_nibble
next

for index = 0 to buf_cnt step 2
in_byte = (in_array[index]<<4) | (in_array[index+1]) 'Form a hex number MSB-LSB
I2CWRITE sda,scl,ctl,eepaddr,[in_byte]
pause 10
eepaddr=eepaddr+1
next
goto eep_loop

lcd_loop:
serin2 in_pin,ser_baud,[wait ("]"),STR in_array\buff_count] 'Wait for ] and the load in_array

for index = 0 to (buff_count - 1)
gosub find 'Get char and place in array
in_array[index]=hex_nibble
next

for index = 0 to (buff_count - 1) step 2
in_byte = (in_array[index]<<4) | (in_array[index+1]) 'Form a hex number MSB-LSB
gosub putbyte


next


goto lcd_loop


It compiles fine for the 18F4580 I'm using, but I don't get anything on the display... I did notice that some links included a controller board (http://www.piclist.com/techref/io/lcd/ks0108.htm) but then this really is a PIC with MAX232 and EEPROM all on one board so shouldn't really make any difference for the code not to display something ?

All I'm really after is for the GLCD to behave as if it were an 8 line x 21 character display - nothing fancy, but on an 18F4580 running at 40 Mhz off a 20 Mhz xtal.... if someone could suggest a simple equivalent of the "hello world"LCD code, or correct me if there are any reasons why this seems such a steep hill to climb with PBP I would be most obliged

Malcolm

richard
- 12th June 2015, 02:14
first up you need to create a font




font8x8:
@ DB 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0 ' Code for char num 32
@ DB 0X08,0X1C,0X1C,0X08,0X08,0X00,0X08,0 ' Code for char num 33
@ DB 0X36,0X36,0X12,0X00,0X00,0X00,0X00,0 ' Code for char num 34
@ DB 0X00,0X14,0X3E,0X14,0X14,0X3E,0X14,0 ' Code for char num 35
@ DB 0X04,0X1C,0X02,0X0C,0X10,0X0E,0X08,0 ' Code for char num 36
@ DB 0X26,0X26,0X10,0X08,0X04,0X32,0X32,0 ' Code for char num 37
@ DB 0X04,0X0A,0X0A,0X04,0X2A,0X12,0X2C,0 ' Code for char num 38
@ DB 0X0C,0X0C,0X04,0X00,0X00,0X00,0X00,0 ' Code for char num 39
@ DB 0X08,0X04,0X04,0X04,0X04,0X04,0X08,0 ' Code for char num 40
@ DB 0X04,0X08,0X08,0X08,0X08,0X08,0X04,0 ' Code for char num 41
@ DB 0X00,0X14,0X1C,0X3E,0X1C,0X14,0X00,0 ' Code for char num 42
@ DB 0X00,0X08,0X08,0X3E,0X08,0X08,0X00,0 ' Code for char num 43
@ DB 0X00,0X00,0X00,0X00,0X00,0X0C,0X0C,4 ' Code for char num 44
@ DB 0X00,0X00,0X00,0X3E,0X00,0X00,0X00,0 ' Code for char num 45
@ DB 0X00,0X00,0X00,0X00,0X00,0X0C,0X0C,0 ' Code for char num 46
@ DB 0X00,0X20,0X10,0X08,0X04,0X02,0X00,0 ' Code for char num 47
@ DB 0X1C,0X22,0X32,0X2A,0X26,0X22,0X1C,0 ' Code for char num 48
@ DB 0X08,0X0C,0X08,0X08,0X08,0X08,0X1C,0 ' Code for char num 49
@ DB 0X1C,0X22,0X20,0X18,0X04,0X02,0X3E,0 ' Code for char num 50
@ DB 0X1C,0X22,0X20,0X1C,0X20,0X22,0X1C,0 ' Code for char num 51
@ DB 0X10,0X18,0X14,0X12,0X3E,0X10,0X10,0 ' Code for char num 52
@ DB 0X3E,0X02,0X02,0X1E,0X20,0X22,0X1C,0 ' Code for char num 53
@ DB 0X18,0X04,0X02,0X1E,0X22,0X22,0X1C,0 ' Code for char num 54
@ DB 0X3E,0X20,0X10,0X08,0X04,0X04,0X04,0 ' Code for char num 55
@ DB 0X1C,0X22,0X22,0X1C,0X22,0X22,0X1C,0 ' Code for char num 56
@ DB 0X1C,0X22,0X22,0X3C,0X20,0X10,0X0C,0 ' Code for char num 57
@ DB 0X00,0X00,0X0C,0X0C,0X00,0X0C,0X0C,0 ' Code for char num 58
@ DB 0X00,0X00,0X0C,0X0C,0X00,0X0C,0X0C,4 ' Code for char num 59
@ DB 0X10,0X08,0X04,0X02,0X04,0X08,0X10,0 ' Code for char num 60
@ DB 0X00,0X00,0X3E,0X00,0X00,0X3E,0X00,0 ' Code for char num 61
@ DB 0X04,0X08,0X10,0X20,0X10,0X08,0X04,0 ' Code for char num 62
@ DB 0X1C,0X22,0X20,0X18,0X08,0X00,0X08,0 ' Code for char num 63
@ DB 0X1C,0X22,0X3A,0X2A,0X3A,0X02,0X1C,0 ' Code for char num 64
@ DB 0X1C,0X22,0X22,0X22,0X3E,0X22,0X22,0 ' Code for char num 65
@ DB 0X1E,0X22,0X22,0X1E,0X22,0X22,0X1E,0 ' Code for char num 66
@ DB 0X1C,0X22,0X02,0X02,0X02,0X22,0X1C,0 ' Code for char num 67
@ DB 0X1E,0X22,0X22,0X22,0X22,0X22,0X1E,0 ' Code for char num 68
@ DB 0X3E,0X02,0X02,0X1E,0X02,0X02,0X3E,0 ' Code for char num 69
@ DB 0X3E,0X02,0X02,0X1E,0X02,0X02,0X02,0 ' Code for char num 70
@ DB 0X1C,0X22,0X02,0X3A,0X22,0X22,0X3C,0 ' Code for char num 71
@ DB 0X22,0X22,0X22,0X3E,0X22,0X22,0X22,0 ' Code for char num 72
@ DB 0X1C,0X08,0X08,0X08,0X08,0X08,0X1C,0 ' Code for char num 73
@ DB 0X20,0X20,0X20,0X20,0X22,0X22,0X1C,0 ' Code for char num 74
@ DB 0X22,0X12,0X0A,0X06,0X0A,0X12,0X22,0 ' Code for char num 75
@ DB 0X02,0X02,0X02,0X02,0X02,0X02,0X3E,0 ' Code for char num 76
@ DB 0X22,0X36,0X2A,0X22,0X22,0X22,0X22,0 ' Code for char num 77
@ DB 0X22,0X26,0X2A,0X32,0X22,0X22,0X22,0 ' Code for char num 78
@ DB 0X1C,0X22,0X22,0X22,0X22,0X22,0X1C,0 ' Code for char num 79
@ DB 0X1E,0X22,0X22,0X1E,0X02,0X02,0X02,0 ' Code for char num 80
@ DB 0X1C,0X22,0X22,0X22,0X2A,0X12,0X2C,0 ' Code for char num 81
@ DB 0X1E,0X22,0X22,0X1E,0X12,0X22,0X22,0 ' Code for char num 82
@ DB 0X1C,0X22,0X02,0X1C,0X20,0X22,0X1C,0 ' Code for char num 83
@ DB 0X3E,0X08,0X08,0X08,0X08,0X08,0X08,0 ' Code for char num 84
@ DB 0X22,0X22,0X22,0X22,0X22,0X22,0X1C,0 ' Code for char num 85
@ DB 0X22,0X22,0X22,0X22,0X22,0X14,0X08,0 ' Code for char num 86
@ DB 0X22,0X22,0X2A,0X2A,0X2A,0X2A,0X14,0 ' Code for char num 87
@ DB 0X22,0X22,0X14,0X08,0X14,0X22,0X22,0 ' Code for char num 88
@ DB 0X22,0X22,0X22,0X14,0X08,0X08,0X08,0 ' Code for char num 89
@ DB 0X1E,0X10,0X08,0X04,0X02,0X02,0X1E,0 ' Code for char num 90



then a way to read the font



get_chr:
@ getaddr _font8x8, _tempPC
tempoff = (chr-$20)*8 + tempPC
for i=0 to 7
readcode tempoff +i ,cga[I]
next


a macro to get the fonts address





asm
getaddr macro Text, Addr
movlw low Text
movwf Addr
movlw High Text
movwf Addr + 1
endm


then put the 8 bytes in array cga[] onto the display


ps this is for a pic18 its not easy to do it this way with a pic16

tempPC var word
tempoff var word
cga var byte[8]
I var byte
chr var byte