' PIC18F46K22 AND Lcd1602_I2C (PCF8574)
' By COS, 2025/04/16, PIC18 OSHONSOFT v5.90
' For simulation only.
' *************************************************************************************
' General configuration
#define CLOCK_FREQUENCY = 64  ' System clock frequency in MHz
#define SINGLE_DECIMAL_PLACES = 1  ' Number of decimal places for floating-point operations
#define STRING_MAX_LENGTH = 30  ' Maximum length for string variables
#define SIMULATION_WAITMS_VALUE = 0
' -------------------------------------------------------------------------
' -------------------------------------------------------------------------
' Main program
Main:
	'**********************************************************************
    AllDigital  ' Set all pins to digital mode

    ' Set all ports as input
    TRISA = 0xFF  ' Set all PORTA pins as input
    TRISB = 0xFF  ' Set all PORTB pins as input
    TRISC = 0xFF  ' Set all PORTC pins as input
    TRISD = 0xFF  ' Set all PORTD pins as input
    TRISE = 0xFF  ' Set all PORTE pins as input
    ' ---------------------------------------------------------------------
    ' Initialize UART at 115200 baud rate (using RC6 for TX and RC7 for RX)
    UART1_Init 115200
    WaitUs 1  ' Delay for stabilization
    ' ---------------------------------------------------------------------
    ' Send initial message through UART
    UART1_Write 0x0C  ' ASCII control character to clear screen
    WaitMs 100  ' Wait for 1 second
    UART1_Write "Ready", CrLf  ' Send "Ready" message with carriage return and line feed

	#define LCD_LINES = 4
	#define LCD_CHARS = 20
	'#define I2CCLOCK_STRETCH = 10
	#define LCD_MODE = lcdPCF8574
	#define LCD_SDA = PORTC.4
	#define LCD_SCL = PORTC.3
	#define LCD_D7 = 7
	#define LCD_D6 = 6
	#define LCD_D5 = 5
	#define LCD_D4 = 4
	#define LCD_BL = 3
	#define LCD_E = 2
	#define LCD_RW = 1
	#define LCD_RS = 0
	#define LCD_ADDR = 7
	WaitMs 50
	lcdPCF_BLhigh
	WaitMs 50

	Lcdinit LcdCurOff
	WaitMs 50

	Lcdout "LCD 20x4 I2C PCF8574"
	Lcdcmdout LcdLine4Home
	Lcdout "0123456789-ABCDEFGHI"
	WaitMs 500

	'WaitMs 500
	lcdPCF_BLlow
	WaitMs 500
	lcdPCF_BLhigh
	WaitMs 2000
	Lcdcmdout LcdCurOff

	Lcd_Out(3, 1, "Load GCRAM.")

	'User-defined characters (big number).
	Lcddefchar 0, %11111, %11111, %11111, 0, 0, 0, 0, 0  'Top horizontal bar.
	Lcd_Out(3, 6, ".")
	WaitMs 500
    Lcddefchar 1, 0, 0, 0, 0, 0, %11111, %11111, %11111  'Bottom horizontal bar.
    Lcddefchar 2, %11111, %11111, %11111, 0, 0, 0, %11111, %11111  'Top and bottom horizontal bar.
	Lcd_Out(3, 7, ".")
	WaitMs 500
    Lcddefchar 3, %11100, %11110, %11110, %11110, %11110, %11110, %11110, %11100  'Left column.
    Lcddefchar 4, %00111, %01111, %01111, %01111, %01111, %01111, %01111, %00111  'Right column.
	Lcd_Out(3, 8, ".")
	WaitMs 500
    Lcddefchar 5, 0, 0, 0, 0, 0, %00011, %00111, %01111  'Bottom Right arrow.
    Lcddefchar 6, %00011, %00111, %01111, 0, 0, 0, 0, 0  'Top Right arrow.
	Lcd_Out(3, 9, ".")
	WaitMs 500
    Lcddefchar 7, 0, 0, 0, 0, 0, %11000, %11100, %11110  'Bottom Left arrow.
	Lcd_Out(3, 10, ".")
	WaitMs 500

	Lcdcmdout LcdLine3Clear
	Dim counter As Integer
	counter = 0

	While True
		LCD_OutBigNum(2, 5, #counter + "ºC")
		counter = counter - 1
		WaitMs 100
	Wend
End
'Function Lcd_Out(line, Xpos, String_Value)
Function Lcd_Out(Line As Byte, Xpos As Byte, txt[20] As String) As Bit
	Lcd_PosXY(Xpos, Line)
	Lcdout txt
End Function
'Function Lcd_PosXY(Xpos, Line)
Function Lcd_PosXY(Xpos As Byte, Line As Byte) As Bit
	If Line = 0 Then Line = 1
	If Line > 4 Then Line = 4
	If Xpos = 0 Then Xpos = 1
	Select Case Line
		Case 1
			Lcdcmdout LcdLine1Pos(Xpos)
		Case 2
			Lcdcmdout LcdLine2Pos(Xpos)
		Case 3
			Lcdcmdout LcdLine3Pos(Xpos)
		Case 4
			Lcdcmdout LcdLine4Pos(Xpos)
	EndSelect
End Function
' **********************************************************************
' Function that enlarges the numeric characters of a string
' Limited string length, written for 2-line
' Line: LCD line.
' Xpos: Starting position to print on the LCD
' strChar: numeric string to write.
' Returns the next position to print (low line).
' *********************************************************************
Function LCD_OutBigNum(Line As Byte, Xpos As Byte, strChar[20] As String) As Byte
    Dim data As Byte	' Mask
    Dim index As Byte  	' Index mask.
    Dim xStr As Byte 	' Character position of then string.
    xStr = 0
	While strChar(xStr) > 0
        Lcd_PosXY(Xpos, Line)	' Lcd cursor position.
		For index = 0 To 5  	' Upper and lower mask print control loop.

			Select Case strChar(xStr)
				' Numeric characters.
				Case "0"
						data = LookUp(4, 0, 3, 4, 1, 3), index			'0
				Case "1"
						data = LookUp(6, 255, " ", 5, 255, 7), index	'1
				Case "2"
						data = LookUp(6, 2, 3, 4, 1, 7), index			'2
				Case "3"
						data = LookUp(6, 2, 3, 5, 1, 3), index			'3
				Case "4"
						data = LookUp(4, 1, 255, " ", " ", 255), index	'4
				Case "5"
						data = LookUp(4, 2, 0, 5, 1, 3), index			'5
				Case "6"
						data = LookUp(4, 2, " ", 4, 1, 3), index		'6
				Case "7"
						data = LookUp(6, 0, 3, " ", 255, " "), index	'7
				Case "8"
						data = LookUp(4, 2, 3, 4, 1, 3), index			'8
				Case "9"
						data = LookUp(4, 2, 3, " ", " ", 255), index	'9

				' Special characters.
				Case "º"
						Lcdout "o"									'º
						Lcd_PosXY(Xpos, Line +1)
						Lcdout " "
						Xpos++
						Exit For
				Case "-"
						Lcdout "_"									'-
						Lcd_PosXY(Xpos, Line +1)
						Lcdout " "
						Xpos++
						Exit For
				Case Else
						Lcdout " "
						Lcd_PosXY(Xpos, Line +1)
						Lcdout strChar(xStr)
						Xpos++
						Exit For
			EndSelect

			' Write the numeric characters.
            Lcdout data  ' Print the current mask.
            ' Select the position where the other half of the enlarged digit should be written.
            If index = 2 Then
                Lcd_PosXY(Xpos, Line +1)  'Line change.
                Xpos = Xpos + 3  ' Position of the other part of the enlarged digit.
            Endif

		Next index

		xStr++  ' Next digit to print.
		'ReturnValue Xpos ' Return to the next position.
	Wend
	ReturnValue Xpos ' Return to the next position.
End Function