2.4インチ液晶ディスプレイ高速表示⑤ 出るか? 新記録。 

 

 人生はゆとりも大切であるが、とことん突き詰めたくなるのは技術者の悪い所かもしれない。 どんなに成功しても100%はありえず、次の日にはもうちょっと良いものが、その次の日にはもっと良いものができると思いながら一歩一歩進んでいく。 それがカイゼンだと私キャッスルは信じて疑っていない。

 そんなことはどうでもいい。 今はこの2.4インチ液晶ディスプレイの限界はどこなのか知りたいだけだ。

 そんなわけで、今回登場するのはArduino DUEマイコンボード。 搭載されているSAM3X8Eプロセッサのクロック周波数は84MHz。 Arduino UNO R4に搭載されているRA4M1プロセッサのクロック周波数は48MHzだから、理論上DUEはUNO R4の1.75倍速いことに。 具体的に言えば、今までさんざん動かしてきた2.4インチ液晶ディスプレイ用のサンプルプログラムの処理で、1秒を切るかもしれないってことだ。

これはワクワクが止まらない。

 どうやるかは前回記事で解説しているので、そちらを参照してもらう。

 

 

 さっそく配線図から。 今回は、SAM3X8EマイコンのPD0端子からPD7端子までの8ビットを使う。 Arduino DUEボードでは、下図を参照されたし。

 

この通りにワイヤー線で繋げばいい

そしてプログラムだが、今回もDUE用に全体を修正しているので全部掲載する。

void Lcd_Writ_Bus(unsigned long d)
{
  REG_PIOD_CODR = 0x00ff;
  REG_PIOD_SODR = d;

  REG_PIOA_CODR = 1 << 16;
  REG_PIOA_SODR = 1 << 16;
}

void Lcd_Write_Com(unsigned char VH)  
{   
  REG_PIOA_CODR = 1 << 24;
  Lcd_Writ_Bus(VH);
}

void Lcd_Write_Data(unsigned char VH)
{
  REG_PIOA_SODR = 1 << 24;
  Lcd_Writ_Bus(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(A3, HIGH);
  delay(5); 
  digitalWrite(A3, LOW);
  delay(15);
  digitalWrite(A3, HIGH);
  delay(15);

  digitalWrite(A2, HIGH);
  digitalWrite(A0, HIGH);
  digitalWrite(A2, LOW);  //CS

  Lcd_Write_Com(0xCB);    //Power control A (CBh)
  Lcd_Write_Data(0x39); 
  Lcd_Write_Data(0x2C); 
  Lcd_Write_Data(0x00); 
  Lcd_Write_Data(0x34); 
  Lcd_Write_Data(0x02); 

  Lcd_Write_Com(0xCF);    //Power control B (CFh)
  Lcd_Write_Data(0x00); 
  Lcd_Write_Data(0X81); 
  Lcd_Write_Data(0X30); 

  Lcd_Write_Com(0xE8);    //Driver timing control A (E8h)
  Lcd_Write_Data(0x84); 
  Lcd_Write_Data(0x11); 
  Lcd_Write_Data(0x7A); 

  Lcd_Write_Com(0xEA);    //Driver timing control B (EAh)
  Lcd_Write_Data(0x66); 
  Lcd_Write_Data(0x00); 

  Lcd_Write_Com(0xED);    //Power on sequence control (EDh)
  Lcd_Write_Data(0x55); 
  Lcd_Write_Data(0x01); 
  Lcd_Write_Data(0X23); 
  Lcd_Write_Data(0X01); 

  Lcd_Write_Com(0xF7);    //Pump ratio control (F7h)
  Lcd_Write_Data(0x10); 

  Lcd_Write_Com(0xC0);    //Power control 
  Lcd_Write_Data(0x23);   //VRH[5:0] 

  Lcd_Write_Com(0xC1);    //Power control 
  Lcd_Write_Data(0x10);   //SAP[2:0];BT[3:0] 

  Lcd_Write_Com(0xC5);    //VCM control 
  Lcd_Write_Data(0x3e);   //Contrast
  Lcd_Write_Data(0x28); 

  Lcd_Write_Com(0xC7);    //VCM control2 
  Lcd_Write_Data(0x86);   //--

  Lcd_Write_Com(0x36);    // Memory Access Control 
  Lcd_Write_Data(0x48);

  Lcd_Write_Com(0x21);    //Display Inversion ON

  Lcd_Write_Com(0x3A);    
  Lcd_Write_Data(0x55); 

  Lcd_Write_Com(0xB1);    
  Lcd_Write_Data(0x00);  
  Lcd_Write_Data(0x18); 

  Lcd_Write_Com(0xB6);    // Display Function Control 
  Lcd_Write_Data(0x08); 
  Lcd_Write_Data(0x82);
  Lcd_Write_Data(0x27);  

  Lcd_Write_Com(0x11);    //Exit Sleep 
  delay(120); 
  Lcd_Write_Com(0x29);    //Display on 
}

void H_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c)                   
{ 
  unsigned int i, j;
  REG_PIOA_CODR = 1 << 23;
  l = l + x;
  Address_set(x, y, l, y);
  j = l * 2;
  for(i = 1; i <= j; i++)
    Lcd_Write_Data(c);
  REG_PIOA_SODR = 1 << 23;
}

void V_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c)                   
{ 
  unsigned int i,j;
  REG_PIOA_CODR = 1 << 23;
  l = l + y;
  Address_set(x, y, x, l);
  j = l * 2;
  for(i = 1; i <= j; i++)
    Lcd_Write_Data(c);
  REG_PIOA_SODR = 1 << 23;
 }

void Rect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c)
{
  H_line(x  , y  , w, c);
  H_line(x  , y+h, w, c);
  V_line(x  , y  , h, c);
  V_line(x+w, y  , h, c);
}

void LCD_Clear(unsigned int j)                   
{ 
  unsigned int i,m;
  REG_PIOA_CODR = 1 << 23;
  Address_set(0, 0, 239, 319);

  for(i = 0; i < 240; i++)
    for(m = 0; m < 320; m++){
      Lcd_Write_Data(j>>8);
      Lcd_Write_Data(j);
    }
  REG_PIOA_SODR = 1 << 23;
}

void setup()
{
  Serial.begin(9600);

  pinMode(25, OUTPUT);   //Data 8bit
  pinMode(26, OUTPUT);
  pinMode(27, OUTPUT);
  pinMode(28, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(29, OUTPUT);
  pinMode(11, OUTPUT);

  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  digitalWrite(A0, HIGH);
  digitalWrite(A1, HIGH);
  digitalWrite(A2, HIGH);
  digitalWrite(A3, HIGH);

  Lcd_Init();
}

void loop()
{  
  unsigned long start = micros();

   LCD_Clear(0xFFFF); 
   LCD_Clear(0x0000); 
   LCD_Clear(0xf800);
   LCD_Clear(0x07E0);
   LCD_Clear(0x001F);
  for(int i = 0; i < 300; i++)
    Rect(random(300), random(300),
         random(300), random(300),
         random(65535));

  Serial.println(micros() - start);
}

これの実行結果は、想定通りと言うか、驚異の0.9秒。

 

早送りしてるように見える・・・

やはり"|="演算子を使うと遅くなるので、全部排除した鬼畜仕様。

 setup関数などの中でいまだにpinMode関数やdigitalWrite関数を使っているのは、ディスプレイの初期設定などは時間測定に含まれていないので遅くてもいいかな、というめんどくさ気分が出てしまったからだ。 正直なところ、DUEで使われているSAM3X8Eプロセッサの端子の初期設定はちょっとめんどくさくて、既存のポートがあるならpinMode関数を使っちゃったほうが楽なのだ。

 

 それにしても、1秒切りはさずがDUEと言う他なし。

クロック周波数だけならESP32の方が速いので、そちらでも試してみたいな。

なんたって240MHzでっせ。 DUEの3倍近く速いのか? まさかね。