Commit c96aadd58b9996def342b679ad6ddb87d35031db
receivedSun, 28. Jul 2024, 18:35:19 (by user sx)
Sun, 28 Jul 2024 16:35:19 +0000 (18:35 +0200)
authorManfred Steiner <sx@htl-kaindorf.at>
Sun, 28 Jul 2024 16:35:11 +0000 (18:35 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Sun, 28 Jul 2024 16:35:11 +0000 (18:35 +0200)
3 files changed:
software/test_2024-07-23/src/main.cpp
software/test_2024-07-23/src/units/lcd.cpp [new file with mode: 0644]
software/test_2024-07-23/src/units/lcd.hpp [new file with mode: 0644]

index 002c340ff2cf77c31993552e637abe9961a7baa4..c9fa88043d96499f608da28e49fba1ccc62a398e 100644 (file)
@@ -14,6 +14,7 @@
 #include "units/r2r.hpp"
 #include "units/motor.hpp"
 #include "units/portexp.hpp"
+#include "units/lcd.hpp"
 
 extern "C" {
    void __cxa_pure_virtual () {
@@ -48,6 +49,7 @@ extern "C" {
    R2r r2r;
    Motor motor;
    PortExp portExp;
+   Lcd lcd;
 
 }
 
@@ -98,7 +100,7 @@ int main () {
    printf("======================================");
 
 
-   TestUnit *unit[] = { &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r, &motor, &portExp  };
+   TestUnit *unit[] = { &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r, &motor, &portExp, &lcd };
 
    for (uint8_t i = 0; i < sizeof(unit) / sizeof(unit[0]); i++) {
       TestUnit *pu = unit[i];
diff --git a/software/test_2024-07-23/src/units/lcd.cpp b/software/test_2024-07-23/src/units/lcd.cpp
new file mode 100644 (file)
index 0000000..0781b6a
--- /dev/null
@@ -0,0 +1,224 @@
+#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()) {};
+}
+
diff --git a/software/test_2024-07-23/src/units/lcd.hpp b/software/test_2024-07-23/src/units/lcd.hpp
new file mode 100644 (file)
index 0000000..11e7749
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef LCD_HPP
+#define LCD_HPP
+
+#include <stdint.h>
+#include "../main.hpp"
+
+class Lcd : public TestUnit {
+   public:
+      Lcd () {};
+      virtual void cleanup ();
+      virtual int8_t run (uint8_t subtest);
+      virtual const char *getName () { return "Lcd"; }
+
+      void init ();
+      uint8_t isBusy ();
+      void writeCommand (uint8_t);
+      void setDDRamAddr (uint8_t);
+      void writeString (const char *s);
+      void writeData (uint8_t);
+      void setCursor (uint8_t row, uint8_t column);
+};
+
+#endif
\ No newline at end of file