class LCD : public Print {
public:
  LCD(uint8_t DS, uint8_t latch, uint8_t clk, uint8_t RS,uint8_t EN, uint8_t LED, uint8_t D4, uint8_t D5, uint8_t D6, uint8_t D7){
    this->RS = RS;
    this->EN = EN;
    this->LED = LED;
    this->D4 = D4;
    this->D5 = D5;
    this->D6 = D6;
    this->D7 = D7;
    this->DS = DS;
    this->latch = latch;
    this->clk = clk;
  }

  LCD(uint8_t DS, uint8_t latch, uint8_t clk){
    RS = 0;
    EN = 2;
    LED = 3;
    D4 = 4;
    D5 = 5;
    D6 = 6;
    D7 = 7;
    this->DS = DS;
    this->latch = latch;
    this->clk = clk;
  }
  void backLight(bool val){
    onebit(LED,val);
  }

  void clear(){
    tx(0x01,0);
  }
  void setCursor(uint8_t c, uint8_t r){
    uint8_t Rows[] = {0x00, 0x40, uint8_t(0x00 + cols), uint8_t(0x40 + cols)};
    tx(0x80|(c + Rows[r]),0);
  }
  void begin(uint8_t rows, uint8_t cols){
    this->rows = rows;
    this->cols = cols;
  pinMode(DS, OUTPUT);
  pinMode(latch, OUTPUT);
  pinMode(clk, OUTPUT);
    tx(0x02,0);
    tx(0x28,0);
    tx(0x0C,0);
    tx(0x06,0);
    tx(0x80,0);
  }
  virtual size_t write(uint8_t value) {
      tx(value, 1);
      return 1;
  }

private:
uint8_t LED,RS,RW,EN,data, DS,latch,clk,D4,D5,D6,D7,rows,cols;

  void onebit(int pos , bool val){
    if(val ==0)
      data = data & ~(1<<pos);
    else
      data = data | (1<<pos);
    port(data);
  }
  void port(int val){
    digitalWrite(latch,0);
    shiftOut(DS,clk, MSBFIRST,val);
    digitalWrite(latch,1);
  }
  void pulse(){
      onebit(EN, 0);
      delayMicroseconds(1);
      onebit(EN, 1);
      delayMicroseconds(1);
      onebit(EN, 0);
      delayMicroseconds(50);
  }
  void fourbit(int val){
    onebit(D4,(val>>0)&1);
    onebit(D5,(val>>1)&1);
    onebit(D6,(val>>2)&1);
    onebit(D7,(val>>3)&1);
    pulse();
  }
  void tx(uint8_t a,  bool rs ){
    onebit(RS,rs);
    fourbit(a >> 4);
    fourbit(a);
  }
};

LCD lcd(2,3,4);
void setup(){
  lcd.begin(16,2);
  lcd.backLight(1);
  lcd.setCursor(0,0);
  lcd.print("Hello");
}
void loop(){
  
}
74HC595