--- /dev/null
+#include <stdio.h>
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include "lcd.hpp"
+#include "../main.hpp"
+
+// PA3 ..... E --> LCD Enable (Verbindung via J25 erforderlich)
+// PD6 ..... R/W --> Read/Write: Read=1, Write=0
+// PD7 ..... RS --> Register Select: Command=0, Data=1
+// PB7:0 ... Data --> Achtung von 5V LCD nicht lesen!
+
+// #define LCD_3V3
+#ifdef LCD_3V3
+ #define DATA_PIN PINB
+#endif
+
+#define DATA_PORT PORTB
+#define DIR_DATA_PORT DDRB
+
+#define PORT_RS PD7
+#define SET_RS_PIN (PORTD |= (1 << PORT_RS))
+#define CLR_RS_PIN (PORTD &= ~(1 << PORT_RS))
+#define SET_DIR_RS (DDRD |= (1 << PORT_RS))
+#define CLR_DIR_RS (DDRD &= ~(1 << PORT_RS))
+
+#define PORT_RW PD6
+#define SET_RW_PIN (PORTD |= (1 << PORT_RW))
+#define CLR_RW_PIN (PORTD &= ~(1 << PORT_RW))
+#define SET_DIR_RW (DDRD |= (1 << PORT_RW))
+#define CLR_DIR_RW (DDRD &= ~(1 << PORT_RW))
+
+#define SET_E_PIN (PORTA |= (1 << PA3))
+#define CLR_E_PIN (PORTA &= ~(1 << PA3))
+#define SET_DIR_E (DDRA |= (1 << PA3))
+#define CLR_DIR_E (DDRA &= ~(1 << PA3))
+
+// Befehle für das Display
+
+#define DISP_CLEAR 0b00000001 // Display clear
+#define DISP_ON 0b00001111 // Display on
+#define DISP_OFF 0b00001011 // Display off
+#define CURSOR_ON 0b00001111 // Cursor on
+#define CURSOR_OFF 0b00001101 // Cursor off
+#define BLINK_ON 0b00001111 // Cursor Blink
+#define BLINK_OFF 0b00001110 // Cursor No Blink
+
+
+void Lcd::cleanup () {
+ DDRA &= ~(1 << PA3);
+ PORTA &= ~(1 << PA3);
+ DDRD &= ~((1 << DDD7) | (1 << DDD6));
+ PORTD &= ~((1 << PORTD7) | (1 << PORTD6));
+ PORTB = 0;
+ DDRB = 0;
+}
+
+int8_t Lcd::run (uint8_t subtest) {
+ if (subtest == 0) {
+ // DDRA |= (1 << PA3);
+ // PORTA &= ~(1 << PA3);
+ // DDRD |= (1 << DDD7) | (1 << DDD6);
+ // PORTD &= ~((1 << PORTD7) | (1 << PORTD6));
+ // PORTB = 0;
+ // DDRB = 0xff;
+ init();
+ #ifdef LCD_3V3
+ printf("init 3.3V LCD");
+ #else
+ printf("init 5V LCD");
+ #endif
+
+ } else if (subtest == 1) {
+ for (uint8_t i = 0; i < 20 * 4; i++) {
+ char c = (char)(i + 32);
+ if (i % 20 == 0) {
+ setCursor(i / 20 + 1, 1);
+ }
+ writeData(c);
+ while (isBusy()) {};
+ }
+ // setCursor(1, 1);
+ // writeString(" 1234567890<>,;.:-_#+");
+ // setCursor(2, 1);
+ // writeString("abcdefghijklmnopqrst");
+ // setCursor(3, 1);
+ // writeString("uvwxyzABCDEFGHIJKLMN");
+ // setCursor(4, 1);
+ // writeString("OPQRSTUVWXYZ ");
+ printf("LCD beschrieben");
+ while (wait(1) == EOF) {
+ }
+
+ } else {
+ printf("end");
+ return -1;
+ }
+ wait(500);
+ return 0;
+}
+
+void Lcd::init () {
+ CLR_RW_PIN; // write
+ CLR_RS_PIN; // command
+ CLR_E_PIN; // E = 0
+
+ SET_DIR_RW;
+ SET_DIR_RS;
+ SET_DIR_E;
+
+ DATA_PORT = 0;
+ DIR_DATA_PORT = 0xff;
+ _delay_ms(16); // min 15ms warten für Reset des Displays
+
+ DATA_PORT = 0b00111011; // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
+ CLR_RW_PIN; // write
+ CLR_RS_PIN; // command
+ SET_E_PIN; // E = 1 (transfer start)
+ _delay_us(10); // min. 10us
+ CLR_E_PIN; // E = 0 (transfer end)
+ _delay_ms(5); // min. 4.1ms
+
+ DATA_PORT = 0b00111011; // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
+ CLR_RW_PIN; // write
+ CLR_RS_PIN; // command
+ SET_E_PIN; // E = 1 (transfer start)
+ _delay_us(10); // min. 10us
+ CLR_E_PIN; // E = 0 (transfer end)
+ _delay_us(100); // min. 100us
+
+ DATA_PORT = 0b00111011; // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
+ CLR_RW_PIN; // write
+ CLR_RS_PIN; // command
+ SET_E_PIN; // E = 1 (transfer start)
+ _delay_us(10); // min. 10us
+ CLR_E_PIN; // E = 0 (transfer end)
+ _delay_us(100); // min. 100us
+
+ writeCommand(DISP_OFF); // Display aus
+ while(isBusy()) {};
+ writeCommand(DISP_ON); // Display ein
+ while(isBusy()) {};
+ writeCommand( BLINK_OFF & CURSOR_OFF); // Blink aus und Cursor aus
+ while(isBusy()) {};
+ writeCommand(DISP_CLEAR);// Clear display
+ while(isBusy()) {};
+}
+
+uint8_t Lcd::isBusy () {
+ #ifdef LCD_3V3
+ DIR_DATA_PORT = 0;
+ SET_RW_PIN; // read
+ CLR_RS_PIN; // command
+ SET_E_PIN; // E = 1 (transfer start)
+ _delay_us(10);
+ uint8_t busy = DATA_PIN & 0x80; // read bit 7 (busy bit)
+ CLR_E_PIN; // E = 0 (transfer end)
+ CLR_RW_PIN;
+ DIR_DATA_PORT = 0xff;
+ return busy != 0;
+ #else
+ _delay_us(200);
+ return 0;
+ #endif
+
+}
+
+void Lcd::writeCommand (uint8_t cmd) {
+ DATA_PORT = cmd;
+ CLR_RW_PIN; // write
+ CLR_RS_PIN; // command
+ SET_E_PIN; // E = 1 (transfer start)
+ _delay_us(10); // min. 10us
+ CLR_E_PIN; // E = 0 (transfer end)
+ _delay_us(10); // min. 10us
+ DATA_PORT = 0;
+}
+
+void Lcd::setDDRamAddr (uint8_t address) {
+ DATA_PORT = address | 0x80;
+ CLR_RW_PIN; // write
+ CLR_RS_PIN; // command
+ SET_E_PIN; // E = 1 (transfer start)
+ _delay_us(10); // min. 10us
+ CLR_E_PIN; // E = 0 (transfer end)
+ _delay_us(10); // min. 10us
+ DATA_PORT = 0;
+}
+
+void Lcd::writeString (const char *s) {
+ while (*s) {
+ writeData(*s++);
+ while (isBusy()) {};
+ }
+}
+
+void Lcd::writeData (uint8_t data) {
+ DATA_PORT = data; // Write data to port
+ SET_RS_PIN; // data
+ CLR_RW_PIN; // command
+ SET_E_PIN; // E = 1 (transfer start)
+ _delay_us(10); // min. 10us
+ CLR_E_PIN; // E = 0 (transfer end)
+ _delay_us(10); // min. 10us
+ CLR_RS_PIN;
+ DATA_PORT = 0;
+}
+
+void Lcd::setCursor (uint8_t row, uint8_t column) {
+ uint8_t b;
+ if (column > 20) {
+ return;
+ }
+ switch (row) {
+ case 1: b = 0x00 + column - 1; break;
+ case 2: b = 0x40 + column - 1; break;
+ case 3: b = 0x14 + column - 1; break;
+ case 4: b = 0x54 + column - 1; break;
+ default: return;
+ }
+ setDDRamAddr(b);
+ while (isBusy()) {};
+}
+