The code is an Arduino-based implementation which intercepts and decodes data intended for an HD44780 LCD screen operating in 4-bit mode. The key use case is to allow you to monitor the data being sent to the LCD, which can be especially useful for troubleshooting, debugging, or enhancing functionality of systems where you don't have direct control over the software that is driving the LCD.
In the setup function, we initialize the Serial communication, define the control and data pins as input and setup an interrupt which is triggered on the falling edge of the EN (Enable) pin. The control pins include RS (Register Select), RW (Read/Write) and EN (Enable) pins.
The loop function checks whether the data is ready to be read. If it is, it prints the corresponding ASCII character to the Serial port and resets the data ready flag.
The readData function, which is called when the interrupt is triggered, first checks if the operation is a write operation and if data is being sent. If it is, it reads the 4-bit part of data from the data pins.
Note: This code assumes that all operations are write operations, i.e., data is always being sent to the LCD. If the device also reads from the LCD, modifications would be needed to handle those operations properly.
// HD44780 DECODER, WRITTEN BY LEONARDO MARTINS 19/01/2019
#define RS_PIN 12 // RS (Register Select) pin
#define RW_PIN 11 // RW (Read/Write) pin
#define EN_PIN 13 // EN (Enable) pin
#define DATA_PINS {33, 32, 35, 34} // Data pins D4, D5, D6 and D7
bool previousEn = LOW; // Previous state of the EN pin
volatile byte data = 0; // Storage for data
volatile bool dataReady = false; // Flag to indicate when data is ready to read
volatile bool highBits = true; // Flag to indicate if we are reading high or low bits
void setup() {
Serial.begin(9600); // Start serial communication
// Set control pins as input
pinMode(RS_PIN, INPUT);
pinMode(RW_PIN, INPUT);
pinMode(EN_PIN, INPUT);
// Set data pins as input
int dataPins[] = DATA_PINS;
for (int i = 0; i < 4; i++) {
pinMode(dataPins[i], INPUT_PULLUP);
}
// Setup the interrupt
attachInterrupt(digitalPinToInterrupt(EN_PIN), readData, FALLING);
}
void loop() {
if (dataReady) {
// Print the corresponding ASCII character to the Serial
Serial.print((char)data);
dataReady = false; // Reset the data ready flag
}
}
void readData() {
// Check if it's a write operation (RW == 0) and data is being sent (RS == 1)
if (digitalRead(RS_PIN) == HIGH) {
// Read the 4-bit part of data
int dataPins[] = DATA_PINS;
byte part = 0;
for (int i = 0; i < 4; i++) {
part |= digitalRead(dataPins[i]) << i;
}
if (highBits) {
// This is the high bits part
data = part << 4;
} else {
// This is the low bits part
data |= part;
dataReady = true; // Indicate that data is ready to read
}
// Flip the highBits flag
highBits = !highBits;
}
}