CPLD IO Detailed description.
The LCD interface is designed to control up to 3 LCD controllers at a time.
It has been tested with HD44780 based LCD controllers and HD62380 based
Graphics LCDs. In theory any other controller which takes up to 2 memory
addresses and uses Motorola R/W and E bus signals can be used.
The LCD controller bus has 8 bidirectional D7..D0 signals. There is a RS
signal which is used to select the register you want to read to write to.
There is a combined R/#W signal which controls where we want to read from or
write to the LCD controller. There is also the E (or strobe) signal. When
the strobe signal is low. The LCD controller does not interpret any of the
commands on the bus. When the signal goes high the command is executed.
The LCD Interface is implemented as several memory mapped registers.
Register Address
LCD_DATA_REG 0x600000 xxxx0000
LCD_CTRL_REG 0x600001 xxxx0001
LCD_STROBE1_REG 0x600006 xxxx0110
LCD_STROBE2_REG 0x60000A xxxx1010
LCD_STROBE3_REG 0x60000E xxxx1110
The LCD_DATA_REG register is used to read or write to the D7..D0 signals.
When you write to that register the CPLD will latch the data into an
internal register. The data will appear on the D7..D0 bus only if the R/#W
signal is in low state and one of the strobe signals is active otherwise the
CPLD will keep the D7..D0 in high impedance state. Note that the CPLD latches
the data in internal registers as part of the write operation. The data will
stay until overridden. You can output the same data multiple times, just by
flipping the E signal a few times.
When you read from the LCD_DATA_REG register the CPLD will output the data
from the LCD controller to the data bus of the MCU only when R/#W signal is
in high state and one of the strobes is active, otherwise the CPLD will keep
the MCU data bus in high impedance state, and you will read noise.
The LCD_CTRL_REG register controls the state of the RS and R/#W signals. The
RS signal is controlled by bit 0 of that register and the R/#W signal is
controlled by bit 1. All other bits are ignored.
When you write into the LCD_CTRL_REG the data is latched into internal
registers and the state of the RS and R/#W signals are changed accordingly.
When you read from the LCD_CTRL_REG register bit 0 and 1 will read the state
of the RS and R/#W signals respectively. Note that those signals are output
only, so the data read will be the same as whatever last you have written in
those bits.
The LCD_STROBEx_REG registers control the strobe signals for LCD1, LCD2 and
LCD3. To set the strobe signal to high, we must write 1 to the bits one and
two of the corresponding strobe register. To set the strobe signal to low, we
have to write 0 to the corresponding strobe register.
Note: Strobe signals are mutually exclusive, that is setting strobe for one
controller to high will automatically set the other two to low.
At reset, the state of the signals is as follows:
RS - low
R/#W - low
Ex - low
D7..D0 - high impedance
example 1 - write 0x28 to the command register (RS=0) of LCD1
begin example 1
write LCD_DATA_REG, 0x28 // the CPLD latches the data to
// internal register
write LCD_CTRL_REG, 0 // R/W# = 0, RS = 0 (Write, Command Reg)
write LCD_STROBE1_REG, 3 // enable strobe for LCD1
// at this point the latched data appears on
// D7..D0
delay ~500 nS // LCD controllers are notoriously slow
write LCD_STROBE1_REG, 0 // clear the strobe, so we can process
// with the next command
end example1
example 2 - write 'A' to the data register (RS=1) of LCD2
begin example2
write LCD_DATA_REG, 'A' // CPLD latches the data
write LCD_CTRL_REG, 1 // R/#W = 0, RS = 1 (Write, Data Reg)
write LCD_STROBE2_REG, 3 // Set strobe for LCD2 to high
delay ~500 nS
write LCD_STROBE2_REG, 0 // Clear strobe
end example2
example 3 - read busy flag from LCD3 (read Command reg)
begin eample3
write LCD_CTRL_REG, 2 // R/#W = 1, RS = 0 (Read, Command Reg)
write LCD_STROBE3_REG, 3 // Set strobe to high
delay ~500 nS // wait for the LCD controller
read result, LCD_DATA_REG // read from LCD_DATA_REG will latch data
// from D7..D0
write LCD_STROBE3_REG, 0 // clear strobe
return (result & 0x80) // Busy Flag is bit 7
end example3
example 4 - write ' ' 5 times to the Data register of LCD1, if your LCD is
set in auto increment mode, this will write 5 spaces from the current cursor
position
begin example4
write LCD_DATA_REG, ' '
write LCD_CTRL_REG, 1 // R/#W = 0, RS = 1 (Data reg)
for(i=0; i < 5; i++)
{
write LCD_STROBE1_REG, 3 // We only flip the strobe
delay ~500 nS // since the data is already
write LCD_STROBE1_REG, 0 // latched inside the CPLD
delay ~450 nS
}
end example4