diff --git a/stm-firmware/include/reflow-controller/ui/lcd.h b/stm-firmware/include/reflow-controller/ui/lcd.h
index bf14743..be13de4 100644
--- a/stm-firmware/include/reflow-controller/ui/lcd.h
+++ b/stm-firmware/include/reflow-controller/ui/lcd.h
@@ -21,4 +21,14 @@
#ifndef __LCD_H__
#define __LCD_H__
+#define LCD_DPORT (GPIOD)
+#define LCD_RCC_MASK RCC_AHB1ENR_GPIODEN
+#define LCD_DATA_BIT_OFFSET (8)
+#define LCD_RS (6)
+#define LCD_E (7)
+
+#define LCD_DATA_MASK (0xFU << LCD_DATA_BIT_OFFSET)
+#define LCD_RS_MASK (1U << LCD_RS)
+#define LCD_E_MASK (1U << LCD_E)
+
#endif /* __LCD_H__ */
diff --git a/stm-firmware/ui/lcd.c b/stm-firmware/ui/lcd.c
index 9fefa6d..41abfc9 100644
--- a/stm-firmware/ui/lcd.c
+++ b/stm-firmware/ui/lcd.c
@@ -18,4 +18,222 @@
* If not, see .
*/
+#include
#include
+#include
+#include
+
+static void lcd_port_clear(void)
+{
+ LCD_DPORT->ODR &= ~(LCD_E_MASK);
+ LCD_DPORT->ODR &= ~(LCD_DATA_MASK | LCD_RS_MASK | LCD_E_MASK);
+}
+
+static void lcd_enable(void)
+{
+ LCD_DPORT->ODR |= LCD_E_MASK;
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ LCD_DPORT->ODR &= ~LCD_E_MASK;
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+ __ASM("nop");
+}
+
+static void lcd_out(uint8_t data)
+{
+ LCD_DPORT->ODR &= ~(LCD_DATA_MASK);
+ LCD_DPORT->ODR |= (data << LCD_DATA_BIT_OFFSET) & LCD_DATA_MASK;
+}
+
+static void lcd_data(uint8_t data)
+{
+ lcd_port_clear();
+ LCD_DPORT->ODR |= LCD_RS_MASK;
+ lcd_out((data>>4) & 0xFU);
+ lcd_enable();
+ lcd_out(data & 0xFU);
+ lcd_enable();
+ systick_wait_ms(1);
+}
+
+static void lcd_command(uint8_t data)
+{
+ lcd_port_clear();
+ lcd_out((data>>4) & 0xFU);
+ lcd_enable();
+ lcd_out(data & 0xFU);
+ lcd_enable();
+ systick_wait_ms(1);
+}
+
+#define LCD_DDADR_LINE1 0x00
+#define LCD_DDADR_LINE2 0x40
+#define LCD_DDADR_LINE3 0x10
+#define LCD_DDADR_LINE4 0x50
+
+// Clear Display -------------- 0b00000001
+#define LCD_CLEAR_DISPLAY 0x01
+
+// Cursor Home ---------------- 0b0000001x
+#define LCD_CURSOR_HOME 0x02
+
+// Set Entry Mode ------------- 0b000001xx
+#define LCD_SET_ENTRY 0x04
+
+#define LCD_ENTRY_DECREASE 0x00
+#define LCD_ENTRY_INCREASE 0x02
+#define LCD_ENTRY_NOSHIFT 0x00
+#define LCD_ENTRY_SHIFT 0x01
+
+// Set Display ---------------- 0b00001xxx
+#define LCD_SET_DISPLAY 0x08
+
+#define LCD_DISPLAY_OFF 0x00
+#define LCD_DISPLAY_ON 0x04
+#define LCD_CURSOR_OFF 0x00
+#define LCD_CURSOR_ON 0x02
+#define LCD_BLINKING_OFF 0x00
+#define LCD_BLINKING_ON 0x01
+
+// Set Shift ------------------ 0b0001xxxx
+#define LCD_SET_SHIFT 0x10
+
+#define LCD_CURSOR_MOVE 0x00
+#define LCD_DISPLAY_SHIFT 0x08
+#define LCD_SHIFT_LEFT 0x00
+#define LCD_SHIFT_RIGHT 0x04
+
+// Set Function --------------- 0b001xxxxx
+#define LCD_SET_FUNCTION 0x20
+
+#define LCD_FUNCTION_4BIT 0x00
+#define LCD_FUNCTION_8BIT 0x10
+#define LCD_FUNCTION_1LINE 0x00
+#define LCD_FUNCTION_2LINE 0x08
+#define LCD_FUNCTION_5X7 0x00
+#define LCD_FUNCTION_5X10 0x04
+
+#define LCD_SOFT_RESET 0x30
+
+// Set CG RAM Address --------- 0b01xxxxxx (Character Generator RAM)
+#define LCD_SET_CGADR 0x40
+
+#define LCD_GC_CHAR0 0
+#define LCD_GC_CHAR1 1
+#define LCD_GC_CHAR2 2
+#define LCD_GC_CHAR3 3
+#define LCD_GC_CHAR4 4
+#define LCD_GC_CHAR5 5
+#define LCD_GC_CHAR6 6
+#define LCD_GC_CHAR7 7
+
+// Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM)
+#define LCD_SET_DDADR 0x80
+
+void lcd_clear(void)
+{
+ lcd_command(LCD_CLEAR_DISPLAY);
+ systick_wait_ms(3);
+}
+
+void lcd_home( void )
+{
+ lcd_command(LCD_CURSOR_HOME);
+ systick_wait_ms(3);
+}
+
+void lcd_setcursor( uint8_t x, uint8_t y )
+{
+ uint8_t data;
+
+ switch (y) {
+ case 0:
+ /* First line */
+ data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
+ break;
+
+ case 1:
+ /* Second Line */
+ data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
+ break;
+
+ case 2:
+ /* Third line */
+ data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
+ break;
+
+ case 3:
+ /* Fourth line */
+ data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
+ break;
+
+ default:
+ return; // für den Fall einer falschen Zeile
+ }
+
+ lcd_command(data);
+}
+
+void lcd_string(const char *data)
+{
+ while (*data != '\0')
+ lcd_data((uint8_t)*data++);
+}
+
+void lcd_init(void)
+{
+ int i;
+
+ rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(LCD_RCC_MASK));
+ lcd_port_clear();
+
+ systick_wait_ms(100);
+ LCD_DPORT->ODR |= (0x3 << LCD_DATA_BIT_OFFSET);
+
+ for (i = 0; i < 3; i++) {
+ lcd_enable();
+ systick_wait_ms(5);
+ }
+
+ // Set 4 Bit mode
+ lcd_port_clear();
+ LCD_DPORT->ODR |= (0x2<AHB1ENR, BITMASK_TO_BITNO(LCD_RCC_MASK));
+}