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