Iskra Neo + ILI9486 TFT 8bit driver (решено)

Тема в разделе "Arduino & Shields", создана пользователем timon, 9 янв 2019.

Метки:
  1. timon

    timon Гик

    Что то совсем уже башка кипит, помогите пожалуйста.

    Имеем Искру от Амперки и работаем только с пинами А1, А2, А3 и А4
    IMG_7275.JPG

    Согласно библиотеке UTFT, где черным по белому:
    Код (C++):
    UTFT::UTFT(byte model, int RS, int WR, int CS, int RST, int SER)
    экранчик на драйвере ILI9486
    IMG_7273.JPG

    и код из примера с инициализацией экрана "ILI9486, A2, A1, A3, A4":
    Код (C++):
    #include <UTFT.h>

    extern uint8_t SmallFont[];

    UTFT myGLCD(ILI9486,A2,A1,A3,A4);

    void setup()
    {
      myGLCD.InitLCD();
      myGLCD.setFont(SmallFont);
    }

    void loop()
    {
      myGLCD.clrScr();
      myGLCD.setColor(255, 0, 0);
      myGLCD.fillRect(0, 0, 479, 13);
      myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1);
      myGLCD.setBackColor(64, 64, 64);
      myGLCD.setColor(255,255,0);
      myGLCD.print("<http://www.RinkyDinkElectronics.com/>", CENTER, 307);
    }
    и пины экрана:
    IMG_7272.JPG
    где нам нужны RS (A2), WR (A1), CS (A3) и RST (A4)

    В итоге - белый экран, ничего не рисуется и как-то странно помаргивающий BUILTIN-светодиод.
    Но код работает, в Serial что нибудь выводится, например.

    Кто нибудь еще с этой китайской корчей сталкивался? )))
    Народ в отзывах к меге подключал успешно, с UTFT работает говорят, в самой UTFT драйвер для ILI9486 имеется.

    Мысли у меня такие: драйвер в UTFT 16-битный и конкретно к этой реализации (написано Bus: 8bit, но что имеют ввиду китайцы мне неведомо) экрана не очень то и подходит...

    #понакупят_г-на )))

    PS: RS/WR в SCL/SDA уже тыкал, не помогло.
     
    Последнее редактирование: 9 янв 2019
    Un_ka нравится это.
  2. b707

    b707 Гуру

    из этой фразы видно, что вам надо немного поднабраться теории и разобраться., чем отличаются экраны 16 и 8 бит
    Ищите библиотеку для 8-битного подключения... и конкретно для своего экранного чипа. Кстати, только 8бит и будет работать на Искре, 16-битную искра не тянет
     
    timon нравится это.
  3. timon

    timon Гик

  4. parovoZZ

    parovoZZ Гуру

    а неужели для этого экрана китайцы не придумали переходника на I2C?
     
  5. timon

    timon Гик

    Да чорт его знает зачем это надо ) Я хоть в этом деле совсем еще мало соображаю но скажу, что по мне так разницы не много через какой интерфейс работать с экраном (ну кроме COM-порта наверное). Мне в 3.5" экране 480х320 за 600р и с 8 дневной бесплатной доставкой - нравится все )
    Попробую вечером завести экран с китайской либой. Я что то все UTFT, UTFT... Популярная либа. А lcdwiki аж на 4-й странице гугла по запросу "ili9486 8bit library" (((
     
  6. parovoZZ

    parovoZZ Гуру

    а в u8lib нет этого контроллера?
     
  7. timon

    timon Гик

    Неа. https://github.com/olikraus/u8glib/wiki/device
    Я с утра столько помоек в интернете обшарил пока нашел что то похожее на нужную мне либу ))) А так-то либы всякие есть, но там чорт ногу сломит - где есть контроллер, но нет 8 бит, где нет контроллера но есть 8 бит.
     
  8. parovoZZ

    parovoZZ Гуру

    открываешь даташит и пишешь сам либу. Делов на неделю с перекурами. Наерна)))
     
  9. timon

    timon Гик

    Я так не умею ))
    Да и экранчик-то с толкача завелся ) Прошу простить за бестолковство ))
     
  10. timon

    timon Гик

    Библиотека китайская весьма тяжелая, простой (и весьма не быстрый) вывод текста уже раздувает скетч до 23кб, в отличии от UTFT, который с не вырезанными шрифтами укладывался в 13кб (а лишних шрифтов там еще килобайт на 5).
    И не вырезать то толком ничего по крупному (до чистки вообще 26кб скетч был), все в кучу навалили (прямо if-ом внутри - если драйвер такой то делаем так, а если другой то вот так) ))
    Пострадаю еще, до тех пор пока spi варианты не пришли, посмотрим как с ними )
     
  11. timon

    timon Гик

    Упражнения продолжаются.

    Удручившись скоростью вывода на экран (очистка чуть более секунды) - решил посмотреть что там и как внутри драйвера. И ужаснулся от осознания того, что любой байт, отправляемый в сторону экрана делится аж на 4 части на Leonardo (на UNO вроде бы можно все на один порт повесить)...

    Как я понял, пины экрана приходят на:
    0 - B4
    1 - B5
    2 - D1
    3 - D0
    4 - D4
    5 - C6
    6 - D7
    7 - E4

    Я их поделил как мог:
    Код (C++):
    #define BMASK 0xF0
    #define CMASK 0x80
    #define DMASK 0x90
    #define EMASK 0x40

    void Lcd_Write2Bus(unsigned char d)
    {
        PORTE = (PORTE & ~EMASK) | (((d) & (0x1<<7))>>1);                
        PORTD = (PORTD & ~DMASK) | (((d) & (0x1<<6))<<1) | ((d) & (0x1<<4));
        PORTC = (PORTC & ~CMASK) | (((d) & (0x1<<5))<<2);                
        PORTB = (PORTB & ~BMASK) | (((d) & ~BMASK)<<4);
    *(portOutputRegister(digitalPinToPort(LCD_WR))) &=  ~digitalPinToBitMask(LCD_WR);
    *(portOutputRegister(digitalPinToPort(LCD_WR)))|=  digitalPinToBitMask(LCD_WR);
    }
    Но не взлетело и не завелось, хотя должно по идее, так как тут копипаст из либы.

    Зато 5кб скетч )) Где я косячу вторые сутки, ребят??
    Код (C++):
    #define LCD_RD   A0
    #define LCD_WR   A1
    #define LCD_RS   A2    
    #define LCD_CS   A3  
    #define LCD_REST A4

    #define BMASK 0xF0
    #define CMASK 0x80
    #define DMASK 0x90
    #define EMASK 0x40

    void Lcd_Write2Bus(unsigned char d)
    {
        PORTE = (PORTE & ~EMASK) | (((d) & (0x1<<7))>>1);                
        PORTD = (PORTD & ~DMASK) | (((d) & (0x1<<6))<<1) | ((d) & (0x1<<4));
        PORTC = (PORTC & ~CMASK) | (((d) & (0x1<<5))<<2);                
        PORTB = (PORTB & ~BMASK) | (((d) & ~BMASK)<<4);
    *(portOutputRegister(digitalPinToPort(LCD_WR))) &=  ~digitalPinToBitMask(LCD_WR);
    *(portOutputRegister(digitalPinToPort(LCD_WR)))|=  digitalPinToBitMask(LCD_WR);
    }


    void Lcd_Write_Com(unsigned char VH)
    {
      *(portOutputRegister(digitalPinToPort(LCD_RS))) &=  ~digitalPinToBitMask(LCD_RS);//LCD_RS=0;
      Lcd_Write2Bus(VH);
    }

    void Lcd_Write_Data(unsigned char VH)
    {
      *(portOutputRegister(digitalPinToPort(LCD_RS)))|=  digitalPinToBitMask(LCD_RS);//LCD_RS=1;
      Lcd_Write2Bus(VH);
    }

    void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
    {
            Lcd_Write_Com(0x2a);
        Lcd_Write_Data(x1>>8);
        Lcd_Write_Data(x1);
        Lcd_Write_Data(x2>>8);
        Lcd_Write_Data(x2);
            Lcd_Write_Com(0x2b);
        Lcd_Write_Data(y1>>8);
        Lcd_Write_Data(y1);
        Lcd_Write_Data(y2>>8);
        Lcd_Write_Data(y2);
        Lcd_Write_Com(0x2c);                          
    }

    void Lcd_Init(void)
    {
      digitalWrite(LCD_REST,HIGH);
      delay(5);
      digitalWrite(LCD_REST,LOW);
      delay(15);
      digitalWrite(LCD_REST,HIGH);
      delay(15);

      digitalWrite(LCD_CS,HIGH);
      digitalWrite(LCD_WR,HIGH);
      digitalWrite(LCD_CS,LOW);  //CS

        Lcd_Write_Com(0xF9);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x08);
        Lcd_Write_Com(0xC0);
        Lcd_Write_Data(0x19);
        Lcd_Write_Data(0x1A);
        Lcd_Write_Com(0xC1);
        Lcd_Write_Data(0x45);
        Lcd_Write_Data(0X00);
        Lcd_Write_Com(0xC2);
        Lcd_Write_Data(0x33);
        Lcd_Write_Com(0xC5);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x28);
        Lcd_Write_Com(0xB1);
        Lcd_Write_Data(0x90);
        Lcd_Write_Data(0x11);
        Lcd_Write_Com(0xB4);
        Lcd_Write_Data(0x02);
        Lcd_Write_Com(0xB6);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x42);
        Lcd_Write_Data(0x3B);
        Lcd_Write_Com(0xB7);
        Lcd_Write_Data(0x07);
        Lcd_Write_Com(0xE0);
        Lcd_Write_Data(0x1F);
        Lcd_Write_Data(0x25);
        Lcd_Write_Data(0x22);
        Lcd_Write_Data(0x0B);
        Lcd_Write_Data(0x06);
        Lcd_Write_Data(0x0A);
        Lcd_Write_Data(0x4E);
        Lcd_Write_Data(0xC6);
        Lcd_Write_Data(0x39);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x00);
        Lcd_Write_Com(0xE1);
        Lcd_Write_Data(0x1F);
        Lcd_Write_Data(0x3F);
        Lcd_Write_Data(0x3F);
        Lcd_Write_Data(0x0F);
        Lcd_Write_Data(0x1F);
        Lcd_Write_Data(0x0F);
        Lcd_Write_Data(0x46);
        Lcd_Write_Data(0x49);
        Lcd_Write_Data(0x31);
        Lcd_Write_Data(0x05);
        Lcd_Write_Data(0x09);
        Lcd_Write_Data(0x03);
        Lcd_Write_Data(0x1C);
        Lcd_Write_Data(0x1A);
        Lcd_Write_Data(0x00);
        Lcd_Write_Com(0xF1);
        Lcd_Write_Data(0x36);
        Lcd_Write_Data(0x04);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x3C);
        Lcd_Write_Data(0x0F);
        Lcd_Write_Data(0x0F);
        Lcd_Write_Data(0xA4);
        Lcd_Write_Data(0x02);
        Lcd_Write_Com(0xF2);
        Lcd_Write_Data(0x18);
        Lcd_Write_Data(0xA3);
        Lcd_Write_Data(0x12);
        Lcd_Write_Data(0x02);
        Lcd_Write_Data(0x32);
        Lcd_Write_Data(0x12);
        Lcd_Write_Data(0xFF);
        Lcd_Write_Data(0x32);
        Lcd_Write_Data(0x00);
        Lcd_Write_Com(0xF4);
        Lcd_Write_Data(0x40);
        Lcd_Write_Data(0x00);
        Lcd_Write_Data(0x08);
        Lcd_Write_Data(0x91);
        Lcd_Write_Data(0x04);
        Lcd_Write_Com(0xF8);
        Lcd_Write_Data(0x21);
        Lcd_Write_Data(0x04);
        Lcd_Write_Com(0x36);
        Lcd_Write_Data(0x48);
        Lcd_Write_Com(0x3A);
        Lcd_Write_Data(0x55);    
        Lcd_Write_Com(0x11);    //Exit Sleep
        delay(120);            
        Lcd_Write_Com(0x29);    //Display on
    }

    void LCD_Clear(unsigned int j)              
    {
      unsigned int i,m;
    Address_set(0,0,320,480);
      digitalWrite(LCD_CS,LOW);


      for(i=0;i<320;i++)
        for(m=0;m<480;m++)
        {
          Lcd_Write_Data(j>>8);
          Lcd_Write_Data(j);

        }
      digitalWrite(LCD_CS,HIGH);
    }

    void setup()
    {
      for(int p=0;p<10;p++)
      {
        pinMode(p,OUTPUT);
      }
      pinMode(A0,OUTPUT);
      pinMode(A1,OUTPUT);
      pinMode(A2,OUTPUT);
      pinMode(A3,OUTPUT);
      pinMode(A4,OUTPUT);
      digitalWrite(A0, HIGH);
      digitalWrite(A1, HIGH);
      digitalWrite(A2, HIGH);
      digitalWrite(A3, HIGH);
      digitalWrite(A4, HIGH);
      Lcd_Init();
    }

    void loop()
    {
       LCD_Clear(0xf800);
       LCD_Clear(0x07E0);
       LCD_Clear(0x001F);
    }
    И еще я вот что подумал - если прицепиться к шине В полностью (впаявшись в В0 дополнительно, это RX LED, остальные 7 пинов доступны) - делить вообще ничего не надо будет и раз в 5 скорость вывода возможно повысится. Не?
    Ведь тогда получится вот так:
    PORTB =d;
    и сэкономлю тактов... 35 на передаче каждого байта ))

    PS. да, я уже думал про STM32 ))
     
    Последнее редактирование: 12 янв 2019
  12. parovoZZ

    parovoZZ Гуру

    в авр говнокод не лезет?
    На ютубе найди канал narodstream. Там вроде видел разбор полета с параллельным интерфейсом.
     
    timon нравится это.
  13. timon

    timon Гик

    Впритык. Ору второй день с китайской либы. Но работает, хоть и медленно и на всю память.

    А попытки отчекрыжить все лишнее с помощью даташита пока не увенчались успехом ))) заведу мой худой 5кб скетч на четырех портах - полезу паяльником эти самые порты исправлять )))
     
  14. parovoZZ

    parovoZZ Гуру

    а что там не понятного в даташите? Как биты на ногах располагаются и коды команд. Вот и все.
     
  15. timon

    timon Гик

    Я расположил как мог и теперь три путя:
    1. Ошибся с распиновкой ног по портам и битами которые за это отвечают
    2. Накосячил с инициализацией в LCD_Init
    3. Отрезал то что еще не понял и сижу такой счастливый, волосы назад ))
     
  16. timon

    timon Гик

    Завел обрезок ))) чуть не чокнулся с этими пинами.
    48BC73E7-AA4F-4115-B52B-AD80D482BC3C.jpeg
    Зато скетч 5кб ))) и скорости никакой...
     
    b707 нравится это.
  17. b707

    b707 Гуру

    отлично. В чем проблема была?
     
  18. timon

    timon Гик

    В первом пункте - ошибся с побитовым раскладыванием d по четырем портам. Там вообще математика суровая случилась )))
     
  19. timon

    timon Гик

    Перепаял искру что бы получить власть над портом В )))
    Теперь можно вместо этого:
    Код (C++):
        uint8_t dr1 = (d) >> 1, dl1 = (d) << 1;
        PORTE = (PORTE & ~EMASK) | (dr1 & (0x1<<6));
        PORTD = (PORTD & ~DMASK) | (dl1 & (0x1<<7)) | (((d) & (0x1<<3))>>3) | (dr1 & (0x1<<1)) |  ((d) & (0x1<<4));
        PORTC = (PORTC & ~CMASK) | (dl1 & (0x1<<6));
        PORTB = (PORTB & ~BMASK) |(((d) & 0x3)<<4);
      digitalWrite(LCD_WR,LOW);
      digitalWrite(LCD_WR,HIGH);
    И этого


    Можно просто писать
    Код (C++):
      PORTB = d;
      digitalWrite(LCD_WR,LOW);
      digitalWrite(LCD_WR,HIGH);
     
    И что я вам скажу, друзья - скорость реально выросла, плюс еще выкинул нафик этот долбаный страх - digitalWrite
    Теперь работает раз в 10 шустрее:
    Код (C++):
      PORTB = d;
      PORTF &= ~(1<<6);
      PORTF |= (1<<6);


    Что сказать - я рад. Не. Я очень рад был выжать из атмеги32 такую скорость на 480х320/16bit
     
    Последнее редактирование: 12 янв 2019
  20. parovoZZ

    parovoZZ Гуру

    Можно сразу целиком регистр писать - будет совсем быстро.