Tobias Müller 9 mesi fa
parent
commit
6b9099002f
1 ha cambiato i file con 108 aggiunte e 77 eliminazioni
  1. 108 77
      Libs/LCD_Shield/__init__.py

+ 108 - 77
Libs/LCD_Shield/__init__.py

@@ -1,7 +1,7 @@
 """
 Author:     Tobias Müller
 Date:       30.06.2023
-Version:    0.7
+Version:    0.9
 
 This file contains classes for LCD, Button and Led control.
 """
@@ -18,8 +18,8 @@ class LCD:
 
     ##############################           Attributes           ##############################
 
-    __lcd_setting_para = {"LCD_PARA_EXT_FUNC": 0x09,        # Extended Function (4 line mode)
-                          "LCD_PARA_BIAS_SET": 0x12,        # Bias Setting (BS1 = 1)
+    __lcd_setting_para = {"LCD_PARA_EXT_FUNC": 0x09,        # Extended Function (4 line mode) # type: ignore
+                          "LCD_PARA_BIAS_SET": 0x12,        # Bias Setting (BS1 = 1) # type: ignore
                           "LCD_PARA_INT_OSC": 0x1B,         # Internal OSC (BS0 = 1, Bias = 1/6)
                           "LCD_PARA_FOL_CON": 0x6E,         # Follower Control (Devider on, Set Value)
                           "LCD_PARA_DIS_CON": 0x0C}         # Display on/off Control (Cursor off, Blink off)
@@ -69,8 +69,8 @@ class LCD:
                  i2c_frequency: int|str = "FAST_MODE",
                  lcd_backlight_pin: int|str = 28,
                  lcd_brightness: int = 100,
-                 lcd_contrast: int = 0x2A,
-                 lcd_ascii_table: int|str = "ROM B",
+                 lcd_contrast: int = 60,
+                 lcd_ascii_rom: int|str = "ROM B",
                  lcd_line_mode: int = 0,
                  lcd_direction_top: int|bool = False):
 
@@ -81,7 +81,7 @@ class LCD:
         self.__lcd_backlight_pin = self.__check_lcd_backlight_pin(lcd_backlight_pin)
         self.__lcd_brightness = self.__check_lcd_brightness(lcd_brightness)
         self.__lcd_contrast = self.__check_lcd_contrast(lcd_contrast)
-        self.__lcd_ascii_table = self.__check_lcd_ascii_table(lcd_ascii_table)
+        self.__lcd_ascii_rom = self.__check_lcd_ascii_rom(lcd_ascii_rom)
         self.__lcd_line_mode = self.__check_lcd_line_mode(lcd_line_mode)
         self.__lcd_direction_top = self.__check_lcd_direction_top(lcd_direction_top)
 
@@ -115,13 +115,13 @@ class LCD:
         self.__set_lcd_brightness()
     
     @property
-    def lcd_ascii_table(self):
-        return self.__lcd_ascii_table
+    def lcd_ascii_rom(self):
+        return self.__lcd_ascii_rom
 
-    @lcd_ascii_table.setter
-    def lcd_ascii_table(self, lcd_ascii_table: int|str):
-        self.__lcd_ascii_table = self.__check_lcd_ascii_table(lcd_ascii_table)
-        self.__set_lcd_ascii_table()
+    @lcd_ascii_rom.setter
+    def lcd_ascii_rom(self, lcd_ascii_rom: int|str):
+        self.__lcd_ascii_rom = self.__check_lcd_ascii_rom(lcd_ascii_rom)
+        self.__set_lcd_ascii_rom()
 
     @property
     def lcd_contrast(self):
@@ -179,12 +179,7 @@ class LCD:
 
     @i2c_sda_pin.setter
     def i2c_sda_pin(self, i2c_sda_pin: int|str):
-        self.__check_i2c_ports(i2c_sda_pin, self.__i2c_scl_pin)
-        self.__deinit_i2c()
-        (self.__i2c_bus,
-         self.__i2c_sda_pin,
-         self.__i2c_scl_pin) = self.__check_i2c_ports(i2c_sda_pin, self.__i2c_scl_pin)
-        self.__init_i2c()
+        self.change_i2c_port(i2c_sda_pin, self.__i2c_scl_pin)
 
     @property
     def i2c_scl_pin(self):
@@ -192,12 +187,7 @@ class LCD:
 
     @i2c_scl_pin.setter
     def i2c_scl_pin(self, i2c_scl_pin: int|str):
-        self.__check_i2c_ports(self.__i2c_sda_pin, i2c_scl_pin)
-        self.__deinit_i2c()
-        (self.__i2c_bus,
-         self.__i2c_sda_pin,
-         self.__i2c_scl_pin) = self.__check_i2c_ports(self.__i2c_sda_pin, i2c_scl_pin)
-        self.__init_i2c()
+        self.change_i2c_port(self.__i2c_sda_pin, i2c_scl_pin)
 
     ##############################         Methods private        ##############################
 
@@ -248,19 +238,20 @@ class LCD:
     def __check_lcd_contrast(lcd_contrast: int):
         if not isinstance(lcd_contrast, int):
             raise ValueError(f"Value \"{lcd_contrast}\" of \"lcd_contrast\" is not type \"int\"!")
-        elif lcd_contrast < 0 or lcd_contrast > 63:
+        elif lcd_contrast < 0 or lcd_contrast > 100:
             raise ValueError(f"Value \"{lcd_contrast}\" of \"lcd_contrast\" is out of range!")
         else:
             return lcd_contrast
 
-    def __check_lcd_ascii_table(self, lcd_ascii_table: int|str):
-        if not isinstance(lcd_ascii_table, int) and not isinstance(lcd_ascii_table, str):
-            raise ValueError(f"Value \"{lcd_ascii_table}\" of \"lcd_ascii_table\" is not type" +
+    def __check_lcd_ascii_rom(self, lcd_ascii_rom: int|str):
+        if not isinstance(lcd_ascii_rom, int) and not isinstance(lcd_ascii_rom, str):
+            raise ValueError(f"Value \"{lcd_ascii_rom}\" of \"lcd_ascii_rom\" is not type" +
                              " \"int\" or \"str\"!")
-        elif lcd_ascii_table not in self.__lcd_rom.keys():
-            raise ValueError(f"Value \"{lcd_ascii_table}\" of \"lcd_ascii_table\" is not supported!")
+        elif((isinstance(lcd_ascii_rom, int) and lcd_ascii_rom not in self.__lcd_rom.keys()) or
+             (isinstance(lcd_ascii_rom, str) and lcd_ascii_rom.upper() not in self.__lcd_rom.keys())):
+            raise ValueError(f"Value \"{lcd_ascii_rom}\" of \"lcd_ascii_rom\" is not supported!")
         else:
-            return lcd_ascii_table
+            return lcd_ascii_rom
 
     def __check_i2c_ports(self, i2c_sda_pin: int|str, i2c_scl_pin: int|str):
         if not isinstance(i2c_sda_pin, int) and not isinstance(i2c_sda_pin, str):
@@ -343,7 +334,7 @@ class LCD:
                   self.__lcd_setting_para["LCD_PARA_DIS_CON"])
         self.__i2c.writeto(self.__i2c_address, bytes(buffer))
         self.__set_lcd_line_mode()
-        self.__set_lcd_ascii_table()
+        self.__set_lcd_ascii_rom()
         self.__set_lcd_contrast()
         self.__set_lcd_direction()
         self.clear()
@@ -364,22 +355,27 @@ class LCD:
     def __set_lcd_brightness(self):
         self.__backlight_pwm.duty_u16(round(65635 * (self.__lcd_brightness / 100)))
 
-    def __set_lcd_ascii_table(self):
+    def __set_lcd_ascii_rom(self):
+        if isinstance(self.__lcd_ascii_rom, str):
+            lcd_ascii_rom = self.__lcd_ascii_rom.upper()
+        else:
+            lcd_ascii_rom = self.__lcd_ascii_rom
         buffer = (self.__lcd_control_para["CONTROL_BYTE_C0"],
                   self.__lcd_control_para["FUNCTION_SET_RE"],
                   self.__lcd_control_para["CONTROL_BYTE_C0"],
                   self.__lcd_rom_para["LCD_PARA_ROM_SEL"],
                   self.__lcd_control_para["CONTROL_BYTE_C0_RS"],
-                  self.__lcd_rom[self.__lcd_ascii_table] << 0x02,
+                  self.__lcd_rom[lcd_ascii_rom] << 0x02,
                   self.__lcd_control_para["CONTROL_BYTE"],
                   self.__lcd_control_para["FUNCTION_SET"])
         self.__i2c.writeto(self.__i2c_address, bytes(buffer))
 
     def __set_lcd_contrast(self):
+        contrast = round(63 * (self.__lcd_contrast / 100))
         buffer = (self.__lcd_control_para["CONTROL_BYTE"],
                   self.__lcd_control_para["FUNCTION_SET_IS"],
-                  self.__lcd_contrast_para["LCD_PARA_POW_CON"] | (self.__lcd_contrast >> 0x04),
-                  self.__lcd_contrast_para["LCD_PARA_CONTRAST"] | (self.__lcd_contrast & 0x0F),
+                  self.__lcd_contrast_para["LCD_PARA_POW_CON"] | (contrast >> 0x04),
+                  self.__lcd_contrast_para["LCD_PARA_CONTRAST"] | (contrast & 0x0F),
                   self.__lcd_control_para["FUNCTION_SET"])
         self.__i2c.writeto(self.__i2c_address, bytes(buffer))
 
@@ -404,6 +400,36 @@ class LCD:
         buffer.append(self.__lcd_control_para["FUNCTION_SET"])
         self.__i2c.writeto(self.__i2c_address, bytes(buffer))
 
+    def __check_keywords(self, keywords: dict[str,int|bool], keys: list[str]):
+        rows = 0x04 if self.__lcd_line_mode == 0x00 else 0x02 if self.__lcd_line_mode == 0x03 else 0x03
+        output = {"rows": rows, "row": 0x01, "column": 0x01, "auto_line_break": True}
+        for key, val in keywords.items():
+            if key not in keys:
+                raise ValueError(f"Keyword \"{key}\" is unknown!")
+            elif key == "row":
+                if not isinstance(val, int):
+                    raise ValueError(f"Value \"{val}\" of keyword \"{key}\" is not type \"int\"!")
+                elif val > rows or val < 1:
+                    raise ValueError(f"Value \"{val}\" of keyword \"{key}\" is out of range!")
+                else:
+                    output.update({key: val})
+            elif key == "column":
+                if not isinstance(val, int):
+                    raise ValueError(f"Value \"{val}\" of keyword \"{key}\" is not type \"int\"!")
+                elif val > self.__lcd_control_para["DISPLAY_COLUMN"] or val < 0x01:
+                    raise ValueError(f"Value \"{val}\" of keyword \"{key}\" is out of range!")
+                else:
+                    output.update({key: val})
+            elif key == "auto_line_break":
+                if not isinstance(val, int) and not isinstance(val, bool):
+                    raise ValueError(f"Value \"{val}\" of keyword \"{key}\" is not type" +
+                                      " \"int\" or \"bool\"!")
+                elif isinstance(val, int) and (val < 0 or val > 1):
+                    raise ValueError(f"Value \"{val}\" of keyword \"{key}\" is out of range!")
+                else:
+                    output.update({key: val})
+        return output.copy()
+
     ##############################         Methods public         ##############################
 
     def change_i2c_port(self, i2c_sda_pin: int|str, i2c_scl_pin: int|str):    
@@ -421,55 +447,60 @@ class LCD:
             elif len(text) == 0:
                 raise ValueError(f"Value \"{text}\" of \"text\" is out of range!")
 
-        def check_keywords(keywords):
-            pass
-
-        buffer = []
-        char=0
+        keys = ("row", "column", "auto_line_break")
+        keys = self.__check_keywords(keywords, keys)
+        rows = keys["rows"]
+        row = keys["row"]
+        column = keys["column"]
+        auto_line_break = keys["auto_line_break"]
+        check_text(text)
         linefeed = ("\n","\r") 
-        column = 0
-        line = 1
-        lines = 4 if self.__lcd_line_mode == 0 else 2 if self.__lcd_line_mode == 3 else 3 
-        
-        if len(keywords) == 0:
-            check_text(text)
-            for row in range(line,lines + 1):
-                print(len(text))
-                if len(text) == 0:
+        buffer = []
+
+        for line in range(row,rows + 0x01):
+            if len(text) == 0x00 or (not auto_line_break and line > row):
+                break
+            buffer.append(self.__lcd_control_para["CONTROL_BYTE_C0"])
+            buffer.append(self.__lcd_control_para["DISPLAY_ROW_" + str(line)] + (column - 0x01))
+            for char in range(0x00, (self.__lcd_control_para["DISPLAY_COLUMN"] - (column - 0x01)) if
+                              len(text) > (self.__lcd_control_para["DISPLAY_COLUMN"] - (column - 0x01)) else
+                              len(text)):
+                if text[char] in linefeed:
+                    text = text[char + 0x01:]
+                    for _ in range(char, (self.__lcd_control_para["DISPLAY_COLUMN"] - (column - 0x01)) if
+                                   len(text) > (self.__lcd_control_para["DISPLAY_COLUMN"] - (column - 0x01)) else
+                                   len(text)):
+                        buffer.append(self.__lcd_control_para["CONTROL_BYTE_C0_RS"])
+                        buffer.append(ord(" "))
                     break
-                buffer.append(self.__lcd_control_para["CONTROL_BYTE_C0"])
-                buffer.append(self.__lcd_control_para["DISPLAY_ROW_" + str(row)])
-                for char in range(0, self.__lcd_control_para["DISPLAY_COLUMN"] if
-                                  len(text) > self.__lcd_control_para["DISPLAY_COLUMN"] else
-                                  len(text)):
-                    if text[char] in linefeed:
-                        text = text[char + 1:]
-                        break
-                    buffer.append(self.__lcd_control_para["CONTROL_BYTE_C0_RS"])
-                    buffer.append(ord(text[char]))
-                else:
-                    text = text[self.__lcd_control_para["DISPLAY_COLUMN"]:] 
-        else:
-            check_text(text)
-            check_keywords(keywords)
-            print(keywords)
+                buffer.append(self.__lcd_control_para["CONTROL_BYTE_C0_RS"])
+                buffer.append(ord(text[char]))
+            else:
+                text = text[self.__lcd_control_para["DISPLAY_COLUMN"] - (column - 0x01):] 
+            column = 0x01
         self.__i2c.writeto(self.__i2c_address, bytes(buffer))
 
     def clear(self, **keywords):
-        buffer = (self.__lcd_control_para["CONTROL_BYTE"],
-                  self.__lcd_control_para["CLEAR_DISPLAY"])
+        buffer = []
+        if len(keywords) == 0:
+            buffer.append(self.__lcd_control_para["CONTROL_BYTE"])
+            buffer.append(self.__lcd_control_para["CLEAR_DISPLAY"])
+        else:
+            keys = ("row", "column")
+            keys = self.__check_keywords(keywords, keys)
+            row = keys["row"]
+            column = keys["column"]
+            buffer.append(self.__lcd_control_para["CONTROL_BYTE_C0"])
+            buffer.append(self.__lcd_control_para["DISPLAY_ROW_" + str(row)] + (column - 0x01))
+            for _ in range(0x00, self.__lcd_control_para["DISPLAY_COLUMN"]):
+                buffer.append(self.__lcd_control_para["CONTROL_BYTE_C0_RS"])
+                buffer.append(ord(" "))
+                if "column" in keywords.keys():
+                    break
         self.__i2c.writeto(self.__i2c_address, bytes(buffer))
 
 if __name__ == "__main__":
-    lcd = LCD(i2c_scl_pin="GP1",
-              i2c_sda_pin=0,
-              i2c_frequency=400000,
-              lcd_backlight_pin=5,
-              lcd_direction_top=False,
-              lcd_line_mode=0,
-              lcd_contrast=40,
-              lcd_brightness=100,
-              lcd_ascii_table="B")
+    lcd = LCD()
     lcd.print("Hallöle")
     sleep_us(2000000)
     lcd.clear()