/*
LCD Pin LCD Function Arduino Pin AVR Pin Register
--------------------------------------------------
7 D0 D2 PD2 PORTD
8 D1 D3 PD3 PORTD
9 D2 D4 PD4 PORTD
10 D3 D5 PD5 PORTD
11 D4 D6 PD6 PORTD
12 D5 D7 PD7 PORTD
13 D6 D8 PB0 PORTB
14 D7 D9 PB1 PORTB
-------------------------------------------------
*/
#include <avr/io.h>
#include <util/delay.h>
// LCD control pins
#define RS PB4
#define EN PB3
void lcdPulseEnable()
{
PORTB |= (1 << EN);
_delay_us(1);
PORTB &= ~(1 << EN);
_delay_us(100);
}
void lcdSendByte(uint8_t byte, uint8_t isData)
{
if (isData)
PORTB |= (1 << RS); // Data mode
else
PORTB &= ~(1 << RS); // Command mode
// Clear previous data bits on PD2–PD7 and PB0–PB1
PORTD &= 0b00000011; // Clear PD2–PD7 (D0–D5)
PORTB &= 0b11111100; // Clear PB0–PB1 (D6–D7)
// Assign bits to correct pins
// D0–D5 → PD2–PD7
PORTD |= (byte << 2) & 0b11111100;
// D6–D7 → PB0–PB1
PORTB |= (byte >> 6) & 0b00000011;
lcdPulseEnable();
_delay_ms(2);
}
void lcdCommand(uint8_t cmd)
{
lcdSendByte(cmd, 0);
}
void lcdData(uint8_t data)
{
lcdSendByte(data, 1);
}
void lcdInit()
{
_delay_ms(20);
lcdCommand(0x38); // 8-bit, 2-line
lcdCommand(0x0C); // Display ON, Cursor OFF
lcdCommand(0x06); // Auto-increment
lcdCommand(0x01); // Clear display
_delay_ms(2);
}
void lcdPrint(const char *str)
{
while (*str)
{
lcdData(*str++);
}
}
void setup()
{
// RS, EN, D6, D7 (PB4, PB3, PB0, PB1)
DDRB |= (1 << RS) | (1 << EN) | (1 << PB0) | (1 << PB1);
// D0–D5 (PD2–PD7)
DDRD |= 0b11111100;
lcdInit();
lcdPrint("Bare-Metal LCD");
}
void loop()
{
// Do nothing
}
/*
//bare metal code using digitalWrite, pinMode functions
#define RS 12
#define EN 11
// D0–D7 connected to D2–D9
const int dataPins[8] = {2, 3, 4, 5, 6, 7, 8, 9};
void pulseEnable() {
digitalWrite(EN, HIGH);
delayMicroseconds(1);
digitalWrite(EN, LOW);
delayMicroseconds(100); // allow LCD to process
}
void sendCommand(uint8_t cmd) {
digitalWrite(RS, LOW); // command mode
// Send each bit to data lines
for (int i = 0; i < 8; i++) {
digitalWrite(dataPins[i], (cmd >> i) & 0x01);
}
pulseEnable();
delay(2);
}
void sendData(uint8_t data) {
digitalWrite(RS, HIGH); // data mode
for (int i = 0; i < 8; i++) {
digitalWrite(dataPins[i], (data >> i) & 0x01);
}
pulseEnable();
delay(2);
}
void lcdInit() {
delay(20); // LCD power-on delay
sendCommand(0x38); // 8-bit, 2 line, 5x8 font
sendCommand(0x0C); // Display ON, Cursor OFF
sendCommand(0x06); // Auto increment cursor
sendCommand(0x01); // Clear display
delay(2);
}
void lcdPrint(const char *str) {
while (*str) {
sendData(*str++);
}
}
void setup() {
pinMode(RS, OUTPUT);
pinMode(EN, OUTPUT);
for (int i = 0; i < 8; i++) {
pinMode(dataPins[i], OUTPUT);
}
lcdInit(); // Initialize LCD
lcdPrint("Hello, Bare Metal!"); // Display message
}
void loop() {
// Nothing to do
}
*/