| SX/B Example: Serial LCD | Examples Index |
' =========================================================================
'
' File...... SERIAL_LCD.SXB
' Purpose... Serial LCD Controller with 8 I/O bits
' Author.... (c) Parallax, Inc. -- All Rights Reserved
' E-mail.... support@parallax.com
' Started...
' Updated... 05 JUL 2006
'
' =========================================================================
' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------
'
' Implements a simple serial LCD controller using the SX28.
'
' This controller is designed to be command-compatible with SEETRON 2x16
' LCD displays, but is fixed at 9600 baud and uses open-true serial mode.
' It also offers extended functions with RC of the SX28
'
' By sending the instruction prefix ($FE) twice, this LCD controller
' enters "extended" function mode. The following extended functions are
' currently available:
'
' $F0, ddr : Set IO port DDR (1 = input, 0 = output; default is %11111111)
' $F1 : Read IO port
' $F2, bits : Write bits to IO port
' $FF : Read LCD RAM (from current cursor position)
' -------------------------------------------------------------------------
' Device Settings
' -------------------------------------------------------------------------
DEVICE SX28, OSCXT2, TURBO, STACKX, OPTIONX
FREQ 4_000_000
ID "SLCD"
' -------------------------------------------------------------------------
' IO Pins
' -------------------------------------------------------------------------
Sio VAR RA.0 ' pull-up via 4.7K
LcdE VAR RA.1 ' pull-down via 4.7K
LcdRW VAR RA.2
LcdRS VAR RA.3
TRIS_Ctrl VAR TRIS_A
LcdBus VAR RB ' RB.0 --> DB0, ...
TRIS_Lcd VAR TRIS_B
IoPort VAR RC
TRIS_IO VAR TRIS_C
' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------
Baud CON "OT9600" ' open for single wire
Cmd CON $FE ' LCD command prefix
' -------------------------------------------------------------------------
' Variables
' -------------------------------------------------------------------------
serByte VAR Byte ' serial IO byte
tmpB1 VAR Byte ' work vars
tmpB2 VAR Byte
tmpW1 VAR Word
' =========================================================================
PROGRAM Start
' =========================================================================
' -------------------------------------------------------------------------
' Subroutine Declarations
' -------------------------------------------------------------------------
DELAY SUB 1, 2 ' delay in milliseconds
DELAY_US SUB 1, 2 ' delay in microseconds
BLIP SUB 0 ' move bus to/from LCD
LCDINIT SUB 0 ' initialize LCD
LCDCMD SUB 1 ' command byte --> LCD
LCDOUT SUB 1 ' byteVar --> LCD
LCDIN SUB 0 ' byteVar <-- LCD
RX_BYTE SUB 0 ' rx from serial I/O
TX_BYTE SUB 1 ' tx to serial I/O
' -------------------------------------------------------------------------
' Program Code
' -------------------------------------------------------------------------
Start:
TRIS_Ctrl = %0001 ' RA.0 = input (serial)
LCDINIT
Main:
serByte = RX_BYTE ' wait for byte
IF serByte = Cmd THEN Do_Command ' command?
Do_Write:
LCDOUT serByte ' no, write char byte
GOTO Main
Do_Command:
serByte = RX_BYTE ' get command byte
IF serByte = Cmd THEN Extended_Cmd ' extended command?
LCDCMD serByte ' no, write cmd byte
GOTO Main
Extended_Cmd:
serByte = RX_BYTE ' get extended command
Set_IO:
IF serByte <> $F0 THEN Read_IO ' check command
serByte = RX_BYTE ' get port configuration
TRIS_IO = serByte ' setup IO port
GOTO Main
Read_IO:
IF serByte <> $F1 THEN Write_IO
DELAY 2 ' delay for host setup
TX_BYTE IoPort ' send port bits to host
GOTO Main
Write_IO:
IF serByte <> $F2 THEN Read_Byte
IoPort = RX_BYTE ' put bits on the port
GOTO Main
Read_Byte:
IF serByte <> $FF THEN Cmd_X
serByte = LCDIN ' read LCD (cursor pos)
DELAY 2 ' delay for host setup
TX_BYTE serByte ' send byte to to host
GOTO Main
Cmd_X: ' for future expansion
'
GOTO Main
' -------------------------------------------------------------------------
' Subroutine Code
' -------------------------------------------------------------------------
' Use: DELAY ms
' -- 'ms' is delay in milliseconds, 1 - 65535
DELAY:
IF __PARAMCNT = 1 THEN
tmpW1 = __PARAM1 ' save byte value
ELSE
tmpW1 = __WPARAM12 ' save word value
ENDIF
PAUSE tmpW1
RETURN
' -------------------------------------------------------------------------
' Use: DELAY us
' -- 'us' is delay in microseconds, 1 - 65535
DELAY_US:
IF __PARAMCNT = 1 THEN
tmpW1 = __PARAM1 ' save byte value
ELSE
tmpW1 = __WPARAM12 ' save word value
ENDIF
PAUSEUS tmpW1
RETURN
' -------------------------------------------------------------------------
' Use: LCDCMD cmdByte
' -- send 'cmdByte' to LCD with RS line low
LCDCMD: ' write command byte
LcdRS = 0
GOTO Lcd_Put
' -------------------------------------------------------------------------
' Use: LCDOUT char
' -- send 'char' to LCD with RS line high
LCDOUT: ' write character byte
LcdRS = 1
' -------------------------------------------------------------------------
Lcd_Put: ' byte --> LCD bus
LcdBus = __PARAM1
' -------------------------------------------------------------------------
BLIP: ' move bus into LCD
LcdE = 1
DELAY_US 2
LcdE = 0
DELAY_US 40 ' instruction delay
RETURN
' -------------------------------------------------------------------------
' Use: char = LCDIN
' -- puts value at LCD cursor position in 'char'
LCDIN:
TRIS_Lcd = %11111111 ' make LCD bus inputs
LcdRS = 1 ' character mode
LcdRW = 1 ' read mode
LcdE = 1 ' move byte to bus
tmpB1 = LcdBus ' grab the byte
LcdE = 0 ' complete the read
LcdRW = 0 ' return to write mode
TRIS_Lcd = %00000000 ' make LCD bus outputs
RETURN tmpB1 ' return byte to caller
' -------------------------------------------------------------------------
' Use: LCDINIT
' -- initialize LCD for 8-bit, 2-line interface
LCDINIT:
DELAY 15 ' power-up delay, 15 ms
TRIS_Lcd = %00000000 ' all outputs
LcdBus = %00110000 ' 8-bit interface
BLIP
DELAY 5 ' delay 4.5 ms (min)
BLIP
DELAY_US 100
BLIP
LCDCMD %00111000 ' multi-line, 5x7 font
LCDCMD %00001100 ' display on, no cursor
LCDCMD %00000110 ' auto-increment cursor
LCDCMD %00000001 ' clear and home LCD
RETURN
' -------------------------------------------------------------------------
' Use: char = RX_BYTE
' -- reads byte from serial input and places in 'char'
RX_BYTE:
SERIN Sio, Baud, tmpB1 ' receive a byte
RETURN tmpB1 ' return to caller
' -------------------------------------------------------------------------
' Use: TX_BYTE char
' -- transmits 'char' over serial connnection
TX_BYTE:
tmpB1 = __PARAM1 ' save byte to send
SEROUT Sio, Baud, tmpB1 ' send the byte
RETURN
The following program demonstrates the features of this serial LCD using a BASIC Stamp 2 microcontroller.
' =========================================================================
'
' File...... SERIAL_LCD_TEST.BS2
' Purpose... Test the SX/B Serial LCD controller
' Author.... (c) Parallax, Inc. -- All Rights Reserved
' E-mail.... support@parallax.com
' Started...
' Updated... 05 JUL 2006
'
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
'
' This program demostrates the SX/B serial LCD controller code. The SX/B
' LCD controller is code-compatible with SEETRON LCD displays, but adds
' extended features.
'
' To access extended features, the intruction commnad (254) is sent twice,
' then followed with the extended command and possible data byte.
'
' Extended commands:
'
' <$FE><$FE><$F0> - Set SX/B IO port DDR (1 = input, 0 = output)
' <$FE><$FE><$F1> - Read SX/B IO port
' <$FE><$FE><$F2><bits> - Write bits to SX/B IO port
' <$FE><$FE><$FF> - Read LCD RAM (current cursor position)
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
Sio PIN 15
' -----[ Constants ]-------------------------------------------------------
#SELECT $STAMP
#CASE BS2, BS2E, BS2PE
T1200 CON 813
T2400 CON 396
T4800 CON 188
T9600 CON 84
T19K2 CON 32
TMidi CON 12
T38K4 CON 6
#CASE BS2SX, BS2P
T1200 CON 2063
T2400 CON 1021
T4800 CON 500
T9600 CON 240
T19K2 CON 110
TMidi CON 60
T38K4 CON 45
#CASE BS2PX
T1200 CON 3313
T2400 CON 1646
T4800 CON 813
T9600 CON 396
T19K2 CON 188
TMidi CON 108
T38K4 CON 84
#ENDSELECT
Inverted CON $4000
Open CON $8000
Baud CON Open | T9600
LcdCls CON $01 ' clear the LCD
LcdHome CON $02 ' move cursor home
LcdCrsrL CON $10 ' move cursor left
LcdCrsrR CON $14 ' move cursor right
LcdDispL CON $18 ' shift chars left
LcdDispR CON $1C ' shift chars right
LcdDDRam CON $80 ' Display Data RAM control
LcdCGRam CON $40 ' Character Generator RAM
LcdLine1 CON $80 ' DDRAM address of line 1
LcdLine2 CON $C0 ' DDRAM address of line 2
LcdSetIO CON $F0 ' set LCD IO port DDR
LcdRdIO CON $F1 ' read from LCD IO port
LcdWrIO CON $F2 ' write to LCD IO port
LcdI CON $FE ' instruction
LcdRdRAM CON $FF ' read from cursor pos
' -----[ Variables ]-------------------------------------------------------
eePntr VAR Word
char VAR Byte
col VAR Byte
idx VAR Nib
ioPort VAR Byte
' -----[ EEPROM Data ]-----------------------------------------------------
CC0 DATA $0E,$1F,$1C,$18,$1C,$1F,$0E,$00
CC1 DATA $0E,$1F,$1F,$18,$1F,$1F,$0E,$00
CC2 DATA $0E,$1F,$1F,$1F,$1F,$1F,$0E,$00
' -----[ Initialization ]--------------------------------------------------
Reset:
PAUSE 500 ' let LCD get ready
SEROUT Sio, Baud, [LcdI, LcdCls]
PAUSE 2
DL_Chars: ' download custom chars
SEROUT Sio, Baud, [LcdI, LcdCGRam]
FOR eePntr = CC0 TO (CC2 + 7)
READ eePntr, char
SEROUT Sio, Baud, [char]
NEXT
SEROUT Sio, Baud, [LcdI, LcdDDRam]
' -----[ Program Code ]----------------------------------------------------
Main:
DEBUG CLS, "SX/B Serial LCD Demo"
SEROUT Sio, Baud, [LcdI, LcdCls]
PAUSE 500
Write_To_LCD:
DEBUG CRSRXY, 0, 2, "Writing to LCD"
SEROUT Sio, Baud, 10, ["SERIAL LCD"]
SEROUT Sio, Baud, 10, [LcdI, LcdLine2 + 7, "WITH SX/B"]
PAUSE 1000
Read_From_LCD:
DEBUG CRSRXY, 0, 4, "Reading LCD L1: ["
SEROUT Sio, Baud, [LcdI, LcdHome]
PAUSE 2
FOR col = 0 TO 15
SEROUT Sio, Baud, [LcdI, LcdI, LcdRdRAM]
SERIN Sio, Baud, [char]
DEBUG char
NEXT
DEBUG "]",
CRSRXY, 0, 5, "Reading LCD L2: ["
SEROUT Sio, Baud, [LcdI, LcdLine2]
PAUSE 2
FOR col = 0 TO 15
SEROUT Sio, Baud, [LcdI, LcdI, LcdRdRAM]
SERIN Sio, Baud, [char]
DEBUG char
NEXT
DEBUG "]"
PAUSE 1000
Animation:
DEBUG CRSRXY, 0, 7, "Custom character demo"
FOR col = LcdLine2 TO (LcdLine2 + 15)
FOR idx = 0 TO 5
SEROUT Sio, Baud, [LcdI, col]
LOOKUP idx, [0, 1, 2, 1, 0, " "], char
SEROUT Sio, Baud, [char]
PAUSE 50
NEXT
NEXT
IO_Port_Test:
DEBUG CRSRXY, 0, 9, "IO Port Test"
SEROUT Sio, Baud, [LcdI, LcdI, LcdSetIO, %10000000]
DEBUG CRSRXY, 0, 10, " - port.7 = "
SEROUT Sio, Baud, [LcdI, LcdI, LcdRdIO]
SERIN Sio, Baud, [char]
DEBUG BIN1 char.BIT7,
CRSRXY, 0, 11, " - Writing to port "
FOR idx = 0 TO 6
char = %00000001 << idx
SEROUT Sio, Baud, [LcdI, LcdI, LcdWrIO, char]
SEROUT Sio, Baud, [LcdI, LcdLine2]
SEROUT Sio, Baud, ["PORT: ", BIN8 char]
PAUSE 250
NEXT
FOR idx = 5 TO 0
char = %00000001 << idx
SEROUT Sio, Baud, [LcdI, LcdI, LcdWrIO, char]
SEROUT Sio, Baud, [LcdI, LcdLine2]
SEROUT Sio, Baud, ["PORT: ", BIN8 char]
PAUSE 250
NEXT
GOTO Main