From ff519e7cac725fcdfbf5764dceba3f8723cbc6f7 Mon Sep 17 00:00:00 2001
From: Xoaquin Castrelo <xoaquin.cb@gmail.com>
Date: Sun, 14 Nov 2021 02:29:27 +0000
Subject: [PATCH] Added an interface to control a 16x2 display.

---
 emb/display.cpp | 113 ++++++++++++++++++++++++++++++++++++++++++++++++
 emb/display.hpp |   9 ++++
 2 files changed, 122 insertions(+)
 create mode 100644 emb/display.cpp
 create mode 100644 emb/display.hpp

diff --git a/emb/display.cpp b/emb/display.cpp
new file mode 100644
index 0000000..f0ad2ef
--- /dev/null
+++ b/emb/display.cpp
@@ -0,0 +1,113 @@
+#include <util/delay.h>
+#include <avr/io.h>
+
+// commands
+#define LCD_CLEARDISPLAY 0x01
+#define LCD_RETURNHOME 0x02
+#define LCD_ENTRYMODESET 0x04
+#define LCD_DISPLAYCONTROL 0x08
+#define LCD_CURSORSHIFT 0x10
+#define LCD_FUNCTIONSET 0x20
+#define LCD_SETCGRAMADDR 0x40
+#define LCD_SETDDRAMADDR 0x80
+
+// flags for display entry mode
+#define LCD_ENTRYRIGHT 0x00
+#define LCD_ENTRYLEFT 0x02
+#define LCD_ENTRYSHIFTINCREMENT 0x01
+#define LCD_ENTRYSHIFTDECREMENT 0x00
+
+// flags for display on/off control
+#define LCD_DISPLAYON 0x04
+#define LCD_DISPLAYOFF 0x00
+#define LCD_CURSORON 0x02
+#define LCD_CURSOROFF 0x00
+#define LCD_BLINKON 0x01
+#define LCD_BLINKOFF 0x00
+
+// flags for display/cursor shift
+#define LCD_DISPLAYMOVE 0x08
+#define LCD_CURSORMOVE 0x00
+#define LCD_MOVERIGHT 0x04
+#define LCD_MOVELEFT 0x00
+
+// flags for function set
+#define LCD_8BITMODE 0x10
+#define LCD_4BITMODE 0x00
+#define LCD_2LINE 0x08
+#define LCD_1LINE 0x00
+#define LCD_5x10DOTS 0x04
+#define LCD_5x8DOTS 0x00
+
+#define RS_lo() PORTD &= ~(1 << PORTD2)
+#define RS_hi() PORTD |=  (1 << PORTD2)
+#define EN_lo() PORTD &= ~(1 << PORTD3)
+#define EN_hi() PORTD |=  (1 << PORTD3)
+
+void send(uint8_t value)
+{
+    PORTD &= 0x0F;
+    PORTB &= 0xF0;
+    
+    PORTD |= value & 0xF0;
+    PORTB |= value & 0x0F;
+    
+    EN_hi();
+    _delay_us(1);
+    EN_lo();
+    _delay_us(50);
+}
+
+void command(uint8_t value)
+{
+    RS_lo();
+    send(value);
+}
+
+void writeDisplay(uint8_t value)
+{
+    RS_hi();
+    send(value);
+}
+
+void clearDisplay()
+{
+    command(LCD_CLEARDISPLAY);
+    _delay_us(2000);
+}
+
+void initDisplay()
+{
+    DDRD |= 0xF0 | (1 << DDD3) | (1 << DDD2);
+    DDRB |= 0x0F;
+    
+    uint8_t _displayfunction = LCD_8BITMODE | LCD_2LINE | LCD_1LINE | LCD_5x8DOTS;
+    
+    _delay_ms(50);
+    
+    RS_lo();
+    EN_lo();
+    
+    command(LCD_FUNCTIONSET | _displayfunction);
+    _delay_us(4500);
+    command(LCD_FUNCTIONSET | _displayfunction);
+    _delay_us(150);
+    command(LCD_FUNCTIONSET | _displayfunction);
+    command(LCD_FUNCTIONSET | _displayfunction);
+    
+    uint8_t _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
+    command(LCD_DISPLAYCONTROL | _displaycontrol);
+    
+    clearDisplay();
+    
+    uint8_t _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
+    command(LCD_ENTRYMODESET | _displaymode);
+}
+
+void setDisplayCursor(uint8_t col, uint8_t row)
+{
+    row &= 1;
+    
+    command(LCD_SETDDRAMADDR | (col + row * 0x40));
+}
+
diff --git a/emb/display.hpp b/emb/display.hpp
new file mode 100644
index 0000000..8e23da0
--- /dev/null
+++ b/emb/display.hpp
@@ -0,0 +1,9 @@
+#ifndef DISPLAY_H
+#define DISPLAY_H
+
+void initDisplay();
+void writeDisplay(uint8_t value);
+void setDisplayCursor(uint8_t col, uint8_t row);
+void clearDisplay();
+
+#endif /* DISPLAY_H */
-- 
GitLab