#define RS 13
#define E 12
/*
You can read data from LCDs, however
In this tutorial I'm only writing to it
Thus, RW pin is set to ground (Write)
and not defined
*/
// const int d0 = 0;
// const int d1 = 1;
// const int d2 = 2;
// const int d3 = 3;
// const int d4 = 4;
// const int d5 = 5;
// const int d6 = 6;
// const int d7 = 7;
/*
You can set and use every pin individually
but you don't need to specify each pin when
doing direct port manipulation
i.e. PORTD = 0X93
0x93 -> 10010011
|
v
d7 d6 d5 d4 d3 d2 d1 d0
1 0 0 1 0 0 1 1
For PORTS and Pinouts:
https://docs.arduino.cc/static/6ec5e4c2a6c0e9e46389d4f6dc924073/4ef49/Pinout-UNOrev3_latest.png
*/
byte customChar[] = {
B00100,
B00100,
B00100,
B11111,
B00100,
B00100,
B00100,
B00100
};
void setup() {
//Setting all PORT D as OUTPUT
DDRD = 0XFF;
pinMode(RS, OUTPUT);
pinMode(E, OUTPUT);
/*
RS LOW -> Command mode
In this mode, the LCD interprets the
data as a command
*/
digitalWrite(RS, LOW);
// 00001111 -> 0x0F Turn on Screen with Blinking Cursor
//Method without Port manipulation
// digitalWrite(d7, LOW);
// digitalWrite(d6, LOW);
// digitalWrite(d5, LOW);
// digitalWrite(d4, LOW);
// digitalWrite(d3, HIGH);
// digitalWrite(d2, HIGH);
// digitalWrite(d1, HIGH);
// digitalWrite(d0, HIGH);
PORTD = 0X0F;
/*
Toggles the Enable pin,
the Display reads the data then
Enable pin is toggle again to LOW
*/
readSentData();
sendCustomCharacter();
printCharacter(0); // Display the custom character at index 0
}
void loop() {
;
}
/*
Commented out portion (using old method; no port manipulation)
is bitwise mapping, basically you turn the character into
an int, then get the n bit and check if that n bit is 1 (HIGH)
or 0 (LOW)
Example with 2nd bit:
'a' -> int('a') -> 01100001
01100001 >> 2
Index 2 bit (right to left, starting at index 0) is 0
01100001 >> 2 & 1 -> 0 & 1 -> 0
Sets the pin to LOW
This step is not needed because all the pins are
in a PORT, so all the bits get set to the corresponding
pin when you set the port to (int)character
*/
void printCharacter(char character) {
// Check if the character is a custom character
if (character >= 0 && character <= 7) {
// Custom character, send its index as data
digitalWrite(RS, HIGH);
PORTD = 0x80 | (character << 3); // Set D7-D3 to the custom character index
readSentData();
} else {
// Standard ASCII character
digitalWrite(RS, HIGH);
// Set the data bits based on the ASCII value of the character
PORTD = (int) character;
readSentData();
}
}
/*
Basic function for printing a string
Iterates through a string and prints each character
If the character is a \n (newline) or the string is
longer than 16 it prints in the second line
secondLineIndexStart is needed because in the case of
a \n, the second line shouldn't start on the 16 index
of the string
*/
void printString(String stringToPrint) {
int stringSize = stringToPrint.length();
bool doNewLine = false;
int secondLineIndexStart = 16;
int secondLineIndexEnd = stringSize;
for (int i = 0; i < 16; i++) {
if (stringToPrint[i] == '\n') {
doNewLine = true;
secondLineIndexStart = i + 1;
break;
}
printCharacter(stringToPrint[i]);
}
if (stringSize > 16 || doNewLine) {
digitalWrite(RS, LOW);
//Move to second line index 0 (Digit after C determines Index -> [C0 - CF])
PORTD = 0XC0;
readSentData();
for (int i = secondLineIndexStart; i < secondLineIndexEnd; i++) {
printCharacter(stringToPrint[i]);
}
}
}
void readSentData() {
digitalWrite(E, HIGH);
digitalWrite(E, LOW);
}
void sendCustomCharacter() {
// Set CGRAM address to start (usually 0x40)
digitalWrite(RS, LOW);
PORTD = 0x40;
readSentData();
// Set RS to HIGH for data mode
digitalWrite(RS, HIGH);
// Send custom character pattern data to CGRAM
for (int i = 0; i < 8; i++) {
PORTD = customChar[i];
readSentData();
}
// Move the cursor back to the display RAM
digitalWrite(RS, LOW);
PORTD = 0x80; // Move to the beginning of the display
readSentData();
}