' ============================================================================= ' Program..... LCD_Main.bas ' Author...... Jon Williams (jonwms@aol.com) ' Copyright... Copyright (c) 1999 Jon Williams ' ' Started..... 22 OCT 1999 ' Updated..... 22 OCT 1999 ' ============================================================================= ' -----[ Program Description ]------------------------------------------------- ' ' This BasicX module provides high-level support of single and multi-line ' character LCDs that use the Hitachi HD44780 (or compatible) driver. ' ' Note: The subroutines in this module were copied (and appropriately ' modified) from SerialPort.bas that is provided with BasicX. ' -----[ Revision History ]---------------------------------------------------- ' ' 22 OCT 99 : Converted SerialPort.bas and tested ' -----[ Constants ]----------------------------------------------------------- Public Const LCD1Line As Byte = 0 ' 1-line LCD Public Const LCDMulti As Byte = 1 ' 2- or 4-line LCD Public Const LCDcmd As Byte = 0 ' byte is command Public Const LCDwrite As Byte = 1 ' byte is data Public Const LCDclear As Byte = &H01 ' clear screen Public Const LCDCrsrHome As Byte = &H02 ' move cursor home Public Const LCDCrsrLeft As Byte = &H10 ' move cursor left Public Const LCDCrsrRight As Byte = &H14 ' move cursor right Public Const LCDDispLeft As Byte = &H18 ' shift display left Public Const LCDDispRight As Byte = &H1C ' shift display right Public Const LCDDDRam As Byte = &H80 ' display RAM address Public Const LCDCGRam As Byte = &H40 ' character RAM address ' -----[ Subroutines ]--------------------------------------------------------- Public Sub LCDPutStr(ByRef tx As String) Dim length As Integer, ch As String * 1, bCh As Byte Dim x As Integer length = Len(tx) For x = 1 To length ch = Mid(tx, x, 1) bCh = Asc(ch) Call LCDPutByte(bCh, LCDwrite) Next End Sub ' ----------------------------------------------------------------------------- Public Sub LCDPutB(ByVal value As Byte) ' Outputs a Byte type to the LCD. Dim x As Long x = CLng(value) Call LCDPutL(x) End Sub ' ----------------------------------------------------------------------------- Public Sub LCDPutI(ByVal value As Integer) ' Outputs an Integer type to the LCD. Dim x As Long x = CLng(value) Call LCDPutL(x) End Sub ' ----------------------------------------------------------------------------- Public Sub LCDPutUI(ByVal value As UnsignedInteger) ' Outputs an UnsignedInteger type to the LCD. Dim x As Long, y As New UnsignedInteger y = Value x = 0 Call BlockMove(2, MemAddress(y), MemAddress(x)) Call LCDPutL(x) End Sub ' ----------------------------------------------------------------------------- Public Sub LCDPutUL(ByVal Value As UnsignedLong) ' Outputs an UnsignedLong type to the LCD. Dim UL As New UnsignedLong, L As Long, Digit As New UnsignedLong Dim I As Integer, Temp As New UnsignedLong ' If the top bit is clear, the number is ready to go. If ((Value And &H80000000) = 0) Then Call LCDPutL(CLng(Value)) Exit Sub End If ' Divide by 10 is done by a right shift followed by a divide by 5. ' First clear top bit so we can do a signed divide. UL = Value UL = UL And &H7FFFFFFF ' Shift to the right 1 bit. L = CLng(UL) L = L \ 2 ' Put the top bit back, except shifted to the right 1 bit. UL = CuLng(L) UL = UL Or &H40000000 ' The number now fits in a signed long. L = CLng(UL) ' Divide by 5. L = L \ 5 Call LCDPutL(L) ' Multiply by 10. Since multiply doesn't work yet for UnsignedLong, we ' have to do the equivalent addition. Temp = CuLng(L) UL = 0 For I = 1 To 10 UL = UL + Temp Next ' Find the rightmost digit. Digit = Value - UL Call LCDPutL(CLng(Digit)) End Sub ' ----------------------------------------------------------------------------- Public Sub LCDPutL(ByVal Operand As Long) ' Outputs a Long type to the serial port. Const NegativeLimit As Long = -2147483648 Const Base As Long = 10 ' Reserve space for "2147483648" Dim Digit(1 To 10) As Byte Dim Tmp As Long Dim NDigits As Integer Dim I As Integer ' Negative limit must be handled as a special case. If (Operand = NegativeLimit) Then Digit(10) = 2 + 48 Digit(9) = 1 + 48 Digit(8) = 4 + 48 Digit(7) = 7 + 48 Digit(6) = 4 + 48 Digit(5) = 8 + 48 Digit(4) = 3 + 48 Digit(3) = 6 + 48 Digit(2) = 4 + 48 Digit(1) = 8 + 48 NDigits = 10 Else NDigits = 0 Tmp = Abs(Operand) Do NDigits = NDigits + 1 Digit(NDigits) = CByte(Tmp Mod Base) + 48 Tmp = Tmp \ Base If Tmp = 0 Then Exit Do End If Loop End If If (Operand < 0) Then Call LCDPutByte(45, LCDwrite) ' Negative sign. End If ' Digits are stored in reverse order of display. For I = NDigits To 1 Step -1 Call LCDPutByte(Digit(I), LCDwrite) Next End Sub ' ----------------------------------------------------------------------------- Public Sub LCDPutSci(ByVal Value As Single) ' Outputs floating point number in scientific notation format. The output ' is to the serial port. Dim Mantissa As Single, Exponent As Integer, LMant As Long Dim D As Integer Call LCDSplitFloat(Value, Mantissa, Exponent) ' Sign. If (Mantissa < 0!) Then Call LCDPutByte(45, LCDwrite) ' dash End If ' Convert mantissa to a 7-digit integer. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 If (LMant > 9999999) Then LMant = 9999999 End If ' First digit of mantissa. D = CInt(LMant \ 1000000) Call LCDPutByte(CByte(D + 48), LCDwrite) ' Decimal point. Call LCDPutByte(46, LCDwrite) ' Remaining digits of mantissa. LMant = LMant Mod 1000000 Call LCDPutL(LMant) ' Exponent. Call LCDPutByte(69, LCDwrite) ' E If (Exponent < 0) Then Call LCDPutByte(45, LCDwrite) ' Dash Else Call LCDPutByte(43, LCDwrite) ' Plus End If Call LCDPutI(Abs(Exponent)) End Sub ' ----------------------------------------------------------------------------- Public Sub LCDPutS(ByVal Value As Single) ' Outputs a floating point number to the serial port. If the number can be ' displayed without using scientific notation, it is. Otherwise scientific ' notation is used. Dim X As Single, DecimalPlace As Integer, Mantissa As Single Dim Exponent As Integer, DigitPosition As Integer, Factor As Long Dim D As Integer, LMant As Long, DecimalHasDisplayed As Boolean ' Special case for zero. If (Value = 0!) Then Call LCDPutByte(48, LCDwrite) ' Zero Call LCDPutByte(46, LCDwrite) ' Decimal Call LCDPutByte(48, LCDwrite) ' Zero Exit Sub End If X = Abs(Value) ' Use scientific notation for values too big or too small. If (X < 0.1) Or (X > 999999.9) Then Call LCDPutSci(Value) Exit Sub End If ' What follows is non-exponent displays for 0.1000000 < Value < 999999.9 ' Sign. If (Value < 0!) Then Call LCDPutByte(45, LCDwrite) ' Dash. End If If (X < 1!) Then Call LCDPutByte(48, LCDwrite) ' Leading zero. Call LCDPutByte(46, LCDwrite) ' Decimal point. DecimalPlace = 0 ' Convert number to a 7-digit integer. LMant = FixL((X * 10000000#) + 0.5) Else Call LCDSplitFloat(X, Mantissa, Exponent) DecimalPlace = Exponent + 2 ' Convert mantissa to a 7-digit integer. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 If (LMant > 9999999) Then LMant = 9999999 End If End If DecimalHasDisplayed = False Factor = 1000000 For DigitPosition = 1 To 7 If (DigitPosition = DecimalPlace) Then Call LCDPutByte(46, LCDwrite) ' Decimal DecimalHasDisplayed = True End If D = CInt(LMant \ Factor) Call LCDPutByte(CByte(D + 48), LCDwrite) LMant = LMant Mod Factor ' Stop trailing zeros, except for one immediately following the ' decimal place. If (LMant = 0) Then If (DecimalHasDisplayed) Then Exit Sub End If End If Factor = Factor \ 10 Next End Sub ' ----------------------------------------------------------------------------- Private Sub LCDSplitFloat(ByVal Value As Single, _ ByRef Mantissa As Single, _ ByRef Exponent As Integer) ' Splits a floating point number into mantissa and exponent. The mantissa ' range is such that 1.0 <= Abs(Mantissa) < 10.0 for nonzero numbers, and ' zero otherwise. Dim X As Single, Factor As Single ' Zero is a special case. If (Value = 0!) Then Mantissa = 0! Exponent = 0 Exit Sub End If X = Abs(Value) Exponent = 0 Factor = 1! ' Multiply or divide by ten to transform number to value between 1 and 10. Do If (X >= 10!) Then X = X / 10! Factor = Factor * 10! Exponent = Exponent + 1 ElseIf (X < 1!) Then X = X * 10! Factor = Factor * 10! Exponent = Exponent - 1 Else ' If we reach this point, then 1.0 <= mantissa < 10.0. Exit Do End If Loop ' Determine mantissa. If (Exponent = 0) Then Mantissa = Value ElseIf (Exponent > 0) Then Mantissa = Value / Factor Else Mantissa = Value * Factor End If End Sub