'------------------------------------------------------------------------------- ' ' Module: Display.bas ' ' Copyright 2003 Donald Kinzer ' All rights reserved. ' ' Permission is granted for private and educational use. To license for ' any other use, contact the author by email at don@kinzers.com. ' ' This module provides functions to interact with an LCD attached to the ' BX-24 by a single pin using serial protocol. It is designed for a Hyundai ' HG-12603A display but may be compatible with others. The display supports ' 8 lines by 24 columns. ' ' This software also supports a clocked serial data mode that requires ' supporting firmware on the display. The advantage of using this new mode ' is that it frees up the serial port for other uses at the expense of ' requiring two communication lines: one for clock and one for data. However, ' if you are already interfacing with other clocked serial devices, you may ' be able to share the data line among all of the devices and clock each ' one separately. ' ' Several routines in this module require row and/or column addresses. The ' addresses are zero-based, i.e., row address range from 0 to 7 and column ' addresses range from 0 to 23. ' '------------------------------------------------------------------------------- Option Explicit '------------------------------------------------------------------------------- ' This defines the pin used to send data to the LCD Private Const LCD_Pin as Byte = 7 ' These define the pins used in the "clocked serial" mode Private Const LCD_Clk_Pin as Byte = 14 Private Const LCD_Data_Pin as Byte = 15 ' modify this for the desired interface mode Private Const useClockedSerialMode as Boolean = TRUE ' parameters for communicating with the display Private Const LCD_PortMask as Byte = &H08 ' 8 data bits, no parity, non-inverted Private Const LCD_Rate as Long = 9600 ' display geometry Private Const DspRows as Byte = 8 Private Const DspCols as Byte = 24 Private Const NumFonts as Byte = 4 ' # of pre-defined fonts Private Const FontMask as Byte = &H1f ' this is the default font Private Const defFont as Byte = 0 Private curFont as Byte ' serial comm management Private const InBufSize as INTEGER = 2 Private const OutBufSize as INTEGER = 10 Private InBuf(1 To InBufSize) as BYTE Private OutBuf(1 To OutBufSize) as BYTE '------------------------------------------------------------------------------- ' '' DisplayInit ' ' Initialize the display for later use. ' Sub DisplayInit() ' set up communication with the LCD If (useClockedSerialMode) Then Call PutPin(LCD_Clk_Pin, bxOutputHigh) Call PutPin(LCD_Data_Pin, bxOutputLow) Else Call PutPin(LCD_Pin, bxOutputLow) Call initComm(LCD_Pin, LCD_PortMask, LCD_Rate) End If ' clear the display Call DisplayClear() ' disable wrapping and scrolling Call DisplaySetWrapScroll(0, 0) ' initialize font management curFont = defFont Call setFont(curFont) End Sub '------------------------------------------------------------------------------- ' '' DisplayRows ' ' Return the number of rows on the display. ' Function DisplayRows() As Byte DisplayRows = DspRows End Function '------------------------------------------------------------------------------- ' '' DisplayCols ' ' Return the number of columns on the display. ' Function DisplayCols() As Byte DisplayCols = DspCols End Function '------------------------------------------------------------------------------- ' '' DisplaySetWrapScroll ' ' Separately enable or disable wrapping and scrolling. ' Sub DisplaySetWrapScroll(ByVal Wrap as Byte, ByVal Scroll as Byte) Dim cmd as Byte ' compose the wrap/scroll command value cmd = &H30 If (Wrap <> 0) Then cmd = cmd + &H01 End If If (Scroll <> 0) Then cmd = cmd + &H02 End If ' send the command Call putByte(&H5c) Call putByte(&H41) Call putByte(cmd) End Sub '------------------------------------------------------------------------------- ' '' DisplayClear ' ' Clear the display. ' Sub DisplayClear() Call putByte(&H0c) End Sub '------------------------------------------------------------------------------- ' '' DisplayClearRow ' ' Clear the specified row on the display. ' Sub DisplayClearRow(ByVal Row as Byte) If (row < dspRows) Then Call putByte(&H5c) Call putByte(&H4c) Call putByte(&H20 + row) End If End Sub '------------------------------------------------------------------------------- ' '' DisplaySetPos ' ' Set the cursor to the given row and column. ' Sub DisplaySetPos(ByVal Row as Byte, ByVal Col as Byte) If ((Row < DspRows) And (Col < DspCols)) Then Call putByte(&H5c) Call putByte(&H42) Call putByte(Col + 32) Call putByte(Row + 32) End If End Sub '------------------------------------------------------------------------------- ' '' DisplayNewLine ' ' Send the indicated number of newline characters to the display. ' Sub DisplayNewLine(ByVal Count as Integer) Do While (count > 0) Call putByte(&H0d) Call putByte(&H0a) count = count - 1 Loop End Sub '------------------------------------------------------------------------------- ' '' DisplaySpace ' ' Send the specified number of spaces to the display. ' Sub DisplaySpace(ByVal cnt as Byte) Do While (cnt > 0) putByte(&H20) cnt = cnt - 1 Loop End Sub '------------------------------------------------------------------------------- ' '' DisplayChar ' ' Send the specified character to the display. Special prefix characters ' are sent as necessary ' Sub DisplayChar(ByVal ch as Byte) If (ch < &H20) Then ' prefix with backslash, shift the character code up by 20 hex putByte(&H5c) putByte(ch + &H20) ElseIf (ch = &H5c) Then ' prefix backslash with backslash putByte(ch) putByte(ch) ElseIf ((ch >= &H7f) And (ch <= &H9f)) Then ' prefix with backslash, shift the character code down by 20 hex putByte(&H5c) putByte(ch - &H20) Else ' OK to send as is putByte(ch) End If End Sub '------------------------------------------------------------------------------- ' '' DisplayCharAt ' ' Display the diven character at the specified row and column. ' Sub DisplayCharAt(ByVal ch as Byte, ByVal Row as Byte, ByVal Col as Byte) Call DisplaySetPos(Row, Col) Call DisplayChar(ch) End Sub '------------------------------------------------------------------------------- ' '' DisplayMultiChar ' ' Send a specified number of the given character to the display. ' Sub DisplayMultiChar(ByVal ch as Byte, ByVal cnt as Byte) Do While (cnt > 0) Call DisplayChar(ch) cnt = cnt - 1 Loop End Sub '------------------------------------------------------------------------------- ' '' DisplayArrayChar ' ' Starting at the specified index, send 'cnt' characters from an array to the display. ' Sub DisplayArrayChar(ByRef charArray() as Byte, ByVal idx as Integer, ByVal cnt as Byte) If (idx >= 0) Then Do While (cnt > 0) Call DisplayChar(charArray(idx)) cnt = cnt - 1 idx = idx + 1 Loop End If End Sub '------------------------------------------------------------------------------- ' '' DisplayCharFont ' ' Select the specified font and then display the given character in that font ' restoring the previously current font. ' Sub DisplayCharFont(ByVal ch as Byte, ByVal font as Byte) If (font >= NumFonts) Then font = curFont ' invalid, use current font ElseIf (font <> curFont) Then Call setFont(font) End If ' display the character Call DisplayChar(ch) If (font <> curFont) Then ' restore current font Call setFont(curFont) End If End Sub '------------------------------------------------------------------------------- ' '' DisplayStringConst ' ' Display a string passed by value (required for string constants). ' Sub DisplayStringConst(ByVal Str as String) Dim MyStr as String MyStr = Str Call DisplayString(MyStr) End Sub '------------------------------------------------------------------------------- ' '' DisplayString ' ' Display the characters of a string. ' Sub DisplayString(ByRef str as String) Dim strLen as Integer Dim i as Integer strLen = Len(str) For i = 1 to strLen Call putByte(Asc(Mid(str, i, 1))) Next End Sub '------------------------------------------------------------------------------- ' '' DisplayCenteredString ' ' Display the given string centered on the current line of the display. It is ' assumed that the current column is the leftmost. ' Sub DisplayCenteredStr(ByRef str as String) Dim strLen as Integer Dim i as Integer, j as Integer strLen = Len(str) If (strLen > CInt(dspCols)) Then strLen = CInt(dspCols) End If ' output centering prefix If (strLen < CInt(dspCols)) Then j = (CInt(dspCols) - strLen) \ 2 Do While (j > 0) putByte(&H20) j = j - 1 Loop End If ' output the string itself For i = 1 to strLen Call putByte(Asc(Mid(str, i, 1))) Next End Sub '------------------------------------------------------------------------------- ' '' DisplaySubStr ' ' Display a number of characters of a string starting at the indicated position. ' Sub DisplaySubStr(ByRef Str as String, ByVal start as Integer, ByVal cnt as Integer) Dim I as Integer For I = 1 to Cnt Call putByte(Asc(Mid(Str, start, 1))) start = start + 1 Next End Sub '------------------------------------------------------------------------------- ' '' DisplayStringAt ' ' Display the specified string at an indicated row and column. ' Sub DisplayStringAt(ByRef Str as String, ByVal Row as Byte, ByVal Col as Byte) Call DisplaySetPos(Row, Col) Call DisplayString(Str) End Sub '------------------------------------------------------------------------------- ' '' DisplayByte ' ' Display the numeric value of a byte. Leading zeros are not displayed. ' Sub DisplayByte(ByVal val as Byte) Dim digit(1 To 3) as Byte Dim cnt as Byte ' generate the digits in the reverse order that they'll be displayed cnt = 0 Do cnt = cnt + 1 digit(cnt) = (val mod 10) + &H30 val = val \ 10 If (val = 0) Then Exit Do End If Loop ' output the digits in the proper order Do While (cnt > 0) Call DisplayChar(digit(cnt)) cnt = cnt - 1 Loop End Sub '------------------------------------------------------------------------------- ' '' DisplayInt ' ' Display a signed numeric value. Leading zeros are not displayed. ' Sub DisplayInt(ByVal val as Integer) Dim digit(1 To 5) as Byte Dim cnt as Byte ' handle the sign first If (val < 0) Then Call DisplayChar(&H2d) val = -val End If ' generate the digits in the reverse order that they'll be displayed cnt = 0 Do cnt = cnt + 1 digit(cnt) = CByte(val mod 10) + &H30 val = val \ 10 If (val = 0) Then Exit Do End If Loop ' output the digits in the proper order Do While (cnt > 0) Call DisplayChar(digit(cnt)) cnt = cnt - 1 Loop End Sub '------------------------------------------------------------------------------- ' '' DisplayByteHex ' ' Display a byte value in hexadecimal. Two hex digits will be displayed. ' Sub DisplayByteHex(ByVal b as Byte) Call displayNibbleHex(b \ 16) Call displayNibbleHex(b) End Sub '------------------------------------------------------------------------------- ' '' DisplayWordHex ' ' Display a word value in hexadecimal. Four hex digits will be displayed. ' Sub DisplayWordHex(ByVal w as Integer) Call DisplayByteHex(CByte(CUint(w) \ 256)) Call DisplayByteHex(CByte(w Mod 256)) End Sub '------------------------------------------------------------------------------- ' '' DisplaySetFont ' ' Set the font for subsequent display of characters in that font. ' Sub DisplaySetFont(ByVal font as Byte) If ((font < NumFonts) And (font <> curFont)) Then Call setFont(font) curFont = font End If End Sub '------------------------------------------------------------------------------- ' '' DisplaySetFontCharBitmap ' ' Set the bitmap for a character in a font. ' Sub DisplaySetFontCharBitmap(ByVal font as Byte, ByVal char as Byte, ByVal bitmap as Integer) Dim i as Byte Call putByte(&H5c) Call putByte(&H44) Call DisplayByteHex(char) Call putByte((font And FontMask) + &H20) ' send the character's bitmap For i = 0 to 7 Call putByte(RAMPeek(bitmap + CInt(i))) Next End Sub '------------------------------------------------------------------------------- ' '' DisplayGetFont ' ' Return the currently selected font. ' Function DisplayGetFont() as Byte DisplayGetFont = curFont End Function '------------------------------------------------------------------------------- ' '' DisplayFontPreview ' ' Display a font preview page. Each font is previewed in two pages, characters ' 00 to 7f on the first page, 80 to ff on the second page. ' Sub DisplayFontPreview(ByVal font as Byte, ByVal page as Byte) ' output the font preview command prefix Call putByte(&H5c) Call putByte(&H40) ' specify the font to preview Call putByte(&H20 + (font And FontMask)) If (page = 0) Then ' select first page Call putByte(&H31) Else ' select second page Call putByte(&H32) End If End Sub '------------------------------------------------------------------------------- ' '' putByte ' ' Send the specified byte to the display directly. ' Private Sub putByte(ByVal b as Byte) If (useClockedSerialMode) Then ' shift out the data manually to avoid clocking too fast Call PutPin(LCD_Data_Pin, GetBit(b, 7)) Call PulseOut(LCD_Clk_Pin, 1, 0) Call PutPin(LCD_Data_Pin, GetBit(b, 6)) Call PulseOut(LCD_Clk_Pin, 1, 0) Call PutPin(LCD_Data_Pin, GetBit(b, 5)) Call PulseOut(LCD_Clk_Pin, 1, 0) Call PutPin(LCD_Data_Pin, GetBit(b, 4)) Call PulseOut(LCD_Clk_Pin, 1, 0) Call PutPin(LCD_Data_Pin, GetBit(b, 3)) Call PulseOut(LCD_Clk_Pin, 1, 0) Call PutPin(LCD_Data_Pin, GetBit(b, 2)) Call PulseOut(LCD_Clk_Pin, 1, 0) Call PutPin(LCD_Data_Pin, GetBit(b, 1)) Call PulseOut(LCD_Clk_Pin, 1, 0) Call PutPin(LCD_Data_Pin, GetBit(b, 0)) Call PulseOut(LCD_Clk_Pin, 1, 0) Else Call PutQueue(OutBuf, b, 1) End If End sub '------------------------------------------------------------------------------- ' '' newLine ' ' Send a newline sequence to the display. ' Private Sub newLine() Call putByte(&H0d) Call putByte(&H0a) End sub '------------------------------------------------------------------------------- ' '' displayNibbleHex ' ' Display the value of the least significant 4 bits of a value in hexadecimal. ' Private Sub displayNibbleHex(ByVal n as Byte) Dim nibChar as Byte n = n And &H0f If (n <= 9) Then nibChar = n + &H30 Else nibChar = (n - 10) + &H41 End If Call putByte(nibChar) End Sub '------------------------------------------------------------------------------- ' '' setFont ' ' Set the current font for subsequent display. ' Private Sub setFont(ByVal font as Byte) If (font < NumFonts) Then Call putByte(&H5c) Call putByte(&H43) Call putByte(&H20 + font) End If End Sub '------------------------------------------------------------------------------- ' '' initComm ' ' Set up the comm channel to talk to the display. ' Private Sub initComm(ByVal pin as Byte, ByVal portMask as Byte, ByVal speed as Long) Call DefineCom3(0, pin, portMask) Call OpenQueue(InBuf, InBufSize) Call OpenQueue(OutBuf, OutBufSize) Call OpenCom(3, speed, InBuf, OutBuf) End Sub