from machine import Pin
import time

class LCD():
    
    def __init__(self, rs_pin, e_pin, d4_pin, d5_pin, d6_pin, d7_pin):
        self.RS = Pin(rs_pin, Pin.OUTPUT) #0 -команды/ 1 - данные
        self.E = Pin(e_pin, Pin.OUTPUT) #стобирующий сигнал
        self.D4 = Pin(d4_pin, Pin.OUTPUT) #байты данных/команды 1
        self.D5 = Pin(d5_pin, Pin.OUTPUT) #байты данных/команды 2
        self.D6 = Pin(d6_pin, Pin.OUTPUT) #байты данных/команды 3
        self.D7 = Pin(d7_pin, Pin.OUTPUT) #байты данных/команды 4
        self.ms_strobe = 0.05 #задержка для стробирующего импульса
        self.ms_after_com = 40 #время на обработку команд
        self.main = main()
        
    def main():
        try:
            setup()
            result = 1
        except Exception as e:
            print('Возникла ошибка иницилизации')
            print(e)
            result = 0
        return result

    def send_LCD(self, RS_value, D4_value, D5_value,D6_value, D7_value):
        """Функция для отправки данных/команд дисплею"""
        self.RS.value(RS_value) #RS устанавливаем 0-у если идут команды, 1-у если идут данные
        self.E.value(0) #E устанавливаем в 0, пока нет стробирующего импульса
        self.D4.value(D4_value) #выставляем на DB4-DB7 логические нули и единицы
        self.D5.value(D5_value)#выставляем на DB4-DB7 логические нули и единицы
        self.D6.value(D6_value)#выставляем на DB4-DB7 логические нули и единицы
        self.D7.value(D7_value)#выставляем на DB4-DB7 логические нули и единицы
        self.E.value(1) #E устанавливаем в 1, есть стробирующего импульс
        time.sleep_ms(self.mks_strobe)#задержка для стробирующего импульса
        self.E.value(0) #E устанавливаем в 0, пока нет стробирующего импульса
    
    def setup(self):
        #команда №6  (установка разрядности)
        self.send_LCD(0,1,1,0,0) #посылаем 0х30 RS=0, DB4=1, DB5=1, DB6=0, DB7=0
        time.sleep_ms(self.ms_after_com) #время на обработку команд
        
        #команда №6 (установка разрядности 4-е бита)
        self.send_LCD(0,0,1,0,0) #посылаем 0х28 старший полубайт RS=0, DB4=0, DB5=1, DB6=0, DB7=0
        time.sleep_ms(self.ms_after_com) #время на обработку команд
        #Посмотреть на мой дисплей инфу
        self.send_LCD(0,0,1,0,0) #повторяем старший полубайт, отправляем 0x2, особенность HD44780
        self.send_LCD(0,0,0,0,1) #посылаем младший полубайт RS=0, DB4=0, DB5=0, DB6=0, DB7=1
        time.sleep_ms(self.ms_after_com) #время на обработку команд
    
    def display_off(self):
        #команда №4 (выключение дисплея) посылаем 0x8
        self.send_LCD(0,0,0,0,0) #старший полубайт, отправляем 0x0 RS=0, DB4=0, DB5=0, DB6=0, DB7=0
        self.send_LCD(0,0,0,0,1)#младший полубайт, отправляем 0x8 RS=0, DB4=0, DB5=0, DB6=0, DB7=1
        time.sleep_ms(self.ms_after_com) #время на обработку команд 
        
    def display_on(self):
        #команда №4 (включение дисплея) посылаем 0x0С на D4-D7
        self.send_LCD(0,0,0,0,0) #старший полубайт, отправляем 0x0 RS=0, DB4=0, DB5=0, DB6=0, DB7=0
        self.send_LCD(0,0,0,1,1) #младший полубайт, отправляем 0xС RS=0, DB4=0, DB5=0, DB6=1, DB7=1
        time.sleep_ms(self.ms_after_com) #время на обработку команд  
    
    def clear(self):
        #команда №1 (сброс дисплея) посылаем 0x1 на D4-D7
        self.send_LCD(0,0,0,0,0) #старший полубайт, отправляем 0x0 RS=0, DB4=0, DB5=0, DB6=0, DB7=0
        self.send_LCD(0,1,0,0,0) #младший полубайт, отправляем 0x1 RS=0, DB4=1, DB5=0, DB6=0, DB7=0
        time.sleep_ms(self.ms_after_com) #время на обработку команд 
    
    def initialization(self):
        time.sleep_ms(20) #при запуске рекомендуется выждать 20 мс
        #команда №6  (установка разрядности)
        setup()
        #команда №4 (выключение дисплея) посылаем 0x8
        display_off()
        #команда №1 (сброс дисплея) посылаем 0x1 на D4-D7
        clear()
        #команда №3 (при записи курсор движется в право, сдвиг запрещен) посылаем 0x6 на D4-D7 -----
        self.send_LCD(0,0,0,0,0) #старший полубайт, отправляем 0x0 RS=0, DB4=0, DB5=0, DB6=0, DB7=0
        self.send_LCD(0,0,1,1,0) #младший полубайт, отправляем 0x6 RS=0, DB4=0, DB5=1, DB6=1, DB7=0
        time.sleep_ms(self.ms_after_com) #время на обработку команд      
        #команда №4 (включение дисплея) посылаем 0x0С на D4-D7
        display_on()
    

          

void send_LCD(byte RS_value,byte DB4_value,byte DB5_value,byte DB6_value,byte DB7_value) {

  digitalWrite(RS,RS_value);  // RS устанавливаем 0-у если идут команды, 1-у если идут данные
  digitalWrite(E, LOW);       // E устанавливаем в 0, пока нет стробирующего импульса

  digitalWrite(D4,DB4_value); // выставляем на DB4-DB7 логические нули и единицы
  digitalWrite(D5,DB5_value); // 
  digitalWrite(D6,DB6_value); // 
  digitalWrite(D7,DB7_value); // 

  digitalWrite(E, HIGH); // E устанавливаем в 1, есть стробирующего импульс
  delayMicroseconds(mks_strobe);  // задержка для стробирующего импульса, подбираем опытным путем
  digitalWrite(E, LOW);  // E устанавливаем в 0, нет стробирующего импульса  

};

void setup() {
  // put your setup code here, to run once:
  pinMode(RS,OUTPUT);
  pinMode(E,OUTPUT);  

  pinMode(D4,OUTPUT);
  pinMode(D5,OUTPUT);
  pinMode(D6,OUTPUT);
  pinMode(D7,OUTPUT);

  // ------------------------------ ИНИЦИАЛИЗАЦИЯ ДИСПЛЕЯ --------------------------------------
  delay(20);             // при запуске рекомендуется выждать 20 мс

  // ----- команда №6 (установка разрядности) посылаем 0x30 на D4-D7 ----- 
  send_LCD(0,1,1,0,0);              // RS=0, DB4=1, DB5=1, DB6=0, DB7=0
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)  
  // ----- конец команда №6 посылаем 0x30 на D4-D7 -----  

  // ----- команда №6 (установка разрядности 4-е бита) посылаем 0x28 на D4-D7 -----

  //старший полубайт, отправляем 0x2
  send_LCD(0,0,1,0,0);              // RS=0, DB4=0, DB5=1, DB6=0, DB7=0
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)        

  //повторяем старший полубайт, отправляем 0x2, особенность HD44780, 
  send_LCD(0,0,1,0,0);              // RS=0, DB4=0, DB5=1, DB6=0, DB7=0

  //младший полубайт, отправляем 0x8
  send_LCD(0,0,0,0,1);              // RS=0, DB4=0, DB5=0, DB6=0, DB7=1
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)          
  // ----- конец команда №6 посылаем 0x28 на D4-D7 -----    

  // ----- команда №4 (выключение дисплея) посылаем 0x8 на D4-D7 -----

  //старший полубайт, отправляем 0x0
  send_LCD(0,0,0,0,0);              // RS=0, DB4=0, DB5=0, DB6=0, DB7=0
  //младший полубайт, отправляем 0x8  
  send_LCD(0,0,0,0,1);              // RS=0, DB4=0, DB5=0, DB6=0, DB7=1
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)  

  // ----- конец команда №4 (выключение дисплея) посылаем 0x8 на D4-D7 -----  

  // ----- команда №1 (сброс дисплея) посылаем 0x1 на D4-D7 -----

  //старший полубайт, отправляем 0x0
  send_LCD(0,0,0,0,0);              // RS=0, DB4=0, DB5=0, DB6=0, DB7=0
  //младший полубайт, отправляем 0x1  
  send_LCD(0,1,0,0,0);              // RS=0, DB4=1, DB5=0, DB6=0, DB7=0
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)    

  // ----- конец команда №1 (сброс дисплея) посылаем 0x1 на D4-D7 -----

  // ----- команда №3 (при записи курсор движется в право) посылаем 0x6 на D4-D7 -----

  //старший полубайт, отправляем 0x0
  send_LCD(0,0,0,0,0);              // RS=0, DB4=0, DB5=0, DB6=0, DB7=0
  //младший полубайт, отправляем 0x6  
  send_LCD(0,0,1,1,0);              // RS=0, DB4=0, DB5=1, DB6=1, DB7=0
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)  

  // ----- конец команда №3 (при записи курсор движется в право) посылаем 0x6 на D4-D7 -----

  // ----- команда №4 (включение дисплея) посылаем 0x0С на D4-D7 -----

  //старший полубайт, отправляем 0x0
  send_LCD(0,0,0,0,0);              // RS=0, DB4=0, DB5=0, DB6=0, DB7=0
  //младший полубайт, отправляем 0xС  
  send_LCD(0,0,0,1,1);              // RS=0, DB4=0, DB5=0, DB6=1, DB7=1
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)  

  // ----- конец команда №4 (включение дисплея) посылаем 0x0С на D4-D7 -----

  // -------------------------- КОНЕЦ ИНИЦИАЛИЗАЦИЯ ДИСПЛЕЯ ----------------------------------

  // ----- данные - символ 'S' посылаем 0x53 на D4-D7 -----

  //старший полубайт, отправляем 0x5
  send_LCD(1,1,0,1,0);              // RS=1, DB4=1, DB5=0, DB6=1, DB7=0
  //младший полубайт, отправляем 0x3  
  send_LCD(1,1,1,0,0);              // RS=1, DB4=1, DB5=1, DB6=0, DB7=0
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)  

  // ----- конец данные - символ 'S' посылаем 0x53 на D4-D7 -----

  // ----- данные - символ '-' посылаем 0x2D на D4-D7 -----

  //старший полубайт, отправляем 0x2
  send_LCD(1,0,1,0,0);              // RS=1, DB4=0, DB5=1, DB6=0, DB7=0
  //младший полубайт, отправляем 0xD  
  send_LCD(1,1,0,1,1);              // RS=1, DB4=1, DB5=1, DB6=0, DB7=0
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)  

  // ----- конец данные - символ '-' посылаем 0x2D на D4-D7 -----

  // ----- данные - символ 'E' посылаем 0x45 на D4-D7 -----

  //старший полубайт, отправляем 0x4
  send_LCD(1,0,0,1,0);              // RS=1, DB4=0, DB5=0, DB6=1, DB7=0
  //младший полубайт, отправляем 0x5
  send_LCD(1,1,0,1,0);              // RS=1, DB4=1, DB5=0, DB6=1, DB7=0
  delayMicroseconds(mks_after_com); // ожидаем 40мкс, время на обработку команд (см. таблицу)  

  // ----- конец данные - символ 'E' посылаем 0x45 на D4-D7 -----  

}
