Quote Originally Posted by EarlyBird2 View Post
Ambrogio,

Any feedback?

If you have no questions then I will post the next improvement which includes the command in the LCD_Write subroutine. I am now looking at using arrays as the next step.
Here it is! including LOOKUP and ARRAYs.

Code:
'****************************************************************
'*  Name    : I2CLCD.BAS                                        *
'*  Author  : Steve Earl                                        *
'*  Notice  : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 17/07/2014                                        *
'*  Version : 1.0                                               *
'*  Notes   : Serial I2C LCD using PBP 2.5                      *
'*          : PCF8574T I2C port expander 20x4 LCD               *
'****************************************************************

define OSC 40     ' set the correct speed here!!
'DEFINE I2C_SLOW 1
SDA         VAR PORTD.2       ; I2C Data pin
SCL         VAR PORTD.3       ; I2C Clock Pin
LCD_Addr CON 78               ; PCF8574T address
LCD_Line_1 con $80
LCD_Line_2 con $A8
LCD_Line_3 con $94
LCD_Line_4 con $D4
LCD_BuffSize    CON 22

LCD_Buff        VAR BYTE[LCD_BuffSize]
'LCD_BuffAddr    CON EXT : @LCD_BuffAddr = _LCD_Buff
LCD_BuffLen     VAR byte        ; Length of data in buffer
LCD_Data        VAR BYTE        ; Data to Send to LCD
LCD_Byte        VAR BYTE        ; Nibbles to Send
LCD_RS          VAR LCD_Byte.0  ; Register Select bit
LCD_RW          VAR LCD_Byte.1  ; Read/Write bit
LCD_E           VAR LCD_Byte.2  ; Enable bit
LCD_BackLight   VAR LCD_Byte.3  ; Backlight 1=ON
LCD_WriteMode   VAR BYTE        ; 1=LowNibble, 2=HighNibble, 3=Both
LCD_CommandMode VAR BIT         ; Indicates next byte is a command
LCD_Byte2       VAR BYTE        ; Same nibble without E bit
LCD_Idx         VAR BYTE


seconds var byte
minutes var byte
hours   var byte

Init:
;----[Initialize the LCD]-------------------------------------------------------
PAUSE 250                           ; LCD Power-on delay
LCD_Backlight = 1                   ; Backlight On
LCD_RW = 0                          ; Write to LCD
LCD_RS = 0                          ; Command Register
LCD_WriteMode = 1                   ;-- Low Nibbles only
LCD_Data = 3                        ; Software Reset 3 times
gosub LCD_Write : PAUSEUS 6000
gosub LCD_Write : PAUSEUS 1000
gosub LCD_Write : PAUSEUS 1000
LCD_Data = 2                        ; Start 4-bit mode
gosub LCD_Write : PAUSEUS 1000
LCD_WriteMode = 3                   ;-- Both Nibbles
LCD_buff[0] = $28                   ; Function Set, 4-bit, 2-line
LCD_buff[1] = $0C                   ; Display ON
LCD_buff[2] = $FE 
LCD_buff[3] = $06                   ; Entry Mode
LCD_buff[4] = $FE 
LCD_buff[5] = $01                   ; Clear Screen
lcd_bufflen = 6
gosub LCD_Buff_Write

;Print Static Background to LCD
for lcd_idx = 0 to 85
               ;|                    | 20 characters
lookup lcd_idx,["     Steve Earl     ",_            ;20
 $FE,lcd_line_2,"   Datageo Limited  ",_            ;+22 = 42
 $FE,lcd_line_3,"     **********     ",_            ;+22 = 64
 $FE,lcd_line_4,"      00:00:00      "],lcd_data    ;+22 = 86  (0-85)
 gosub lcd_write
next

;Set up fixed buffer characters
lcd_bufflen = 10                     ;8 characters in clock + $FE + LCD_Line
LCD_buff[0] = $FE                   ;Command is next
LCD_buff[1] = lcd_line_4 + 6        ;Move to line 4 col 7
LCD_buff[4] = ":"                   ;Fixed characters
LCD_buff[7] = ":"                   ;       "
main:                               ;Count seconds and refresh the clock
for hours = 0 to 23
    for minutes = 0 to 59
        for seconds = 0 to 59  
            LCD_buff[2] = (hours dig 1)+48  
            LCD_buff[3] = (hours dig 0)+48 
            LCD_buff[5] = (minutes dig 1)+48 
            LCD_buff[6] = (minutes dig 0)+48 
            LCD_buff[8] = (seconds dig 1)+48 
            LCD_buff[9]= (seconds dig 0)+48 
            gosub lcd_buff_write
            pause 1000
        next    ;second
    next    ;minute
next    ;hour
goto main

LCD_WRITE:
if lcd_data = $FE then
    lcd_commandMode = 1                 ;Next byte Command
    lcd_rs = 0                          ;Switch to Command Register
else                                              
    LCD_E = 1                     
    IF LCD_WriteMode.1 = 1 THEN          ; Write High Nibble
     LCD_Byte = (LCD_Byte & $0F) | (LCD_Data  & $F0)
     LCD_Byte2 = LCD_Byte & $FB    
     I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2]
    ENDIF
    
    IF LCD_WriteMode.0 = 1 THEN     ; Write Low Nibble
     LCD_Byte = (LCD_Byte & $0F) | ((LCD_Data << 4 )& $F0)
     LCD_Byte2 = LCD_Byte & $FB
     I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2]
    ENDIF
    if lcd_commandmode then
     lcd_commandmode = 0              ;Reset to data
     lcd_rs = 1                       ;Switch to Data Register
     pause 2
    endif
endif
return

Lcd_Buff_Write:
 for lcd_idx = 0 to lcd_bufflen - 1
  lcd_data=lcd_buff[LCD_idx]
  gosub LCD_Write
 next
return