Arduino UNO R4でJpeg画像ファイル展開を選択式に 

 

 前回の記事で、Arduino UNO R4を使ってJpegファイルを展開してみた。

前回記事を読んでない人はここを参照。

 

 

 前回は、ファイル名を変数に直接入れているので、違う画像を表示させたかったらいちいちプログラム内のファイル名を書き直してコンパイルをし直さなければならない。

「そんなのはめんどくさい。」という要望もあろうかと、リストから選択式にしてみた。

 

処理の順番は、

①シリアルモニターを開くまで待機。

②Arduinoボードや液晶ディスプレイの初期化

③SDカードの内容をシリアルモニター上にリスト表示。

④シリアルモニターから表示したいファイルの番号を入力。

⑤選択されたファイルを液晶ディスプレイに表示。

⑥ ③に戻る。

という感じ。

 

ただ、選択したファイルを特にチェックもせずに表示させているので、プログラム的には課題は多々残っている。

・320×240ドットの横長画像を想定しているので、縦長画像だとオーバーレイしてしまう。 → 横長か縦長かでディスプレイ設定を変える。

・320×240ドットより大きい画像はオーバーレイしてしまう。 → 液晶ディスプレイ内に収まるように縮尺を変える。

・ファイル名のチェックをしていない。 → 拡張子が".jpg"以外は無視などの処理。

・ファイル一覧にjpegファイル以外もある。 → ".jpg"だけ表示。

・選択できるのはルートフォルダのファイルだけ。 → フォルダ移動できるようにする。

 

などなど課題は山積みだ。 キャッスル的には上のオーバーレイしてしまう対策をしたいとは思っているが、気が向いたらやってみる。

その他は・・・しらね。

 

 そんなわけで、ちょいちょい制約はあるがやってみたいという人は、下のプログラムを実行してみてくれい。

 

 

 注意点は、前回同様 Arduino UNO R4 MINIMAかWiFiかによってLcd_Writ_Bus関数内を変える必要がある。

それから、このプログラムはシリアルモニターを開かないと動かないようになっている。

#include <SD.h>
#include "JPEGDecoder.h"
#define SDCS 10  // CS Pin of SD card 
char filename[15];  //file name
unsigned int filecount;

void Lcd_Writ_Bus(unsigned char d)
{
//**Arduino UNO R4 MINIMA ではこちらを使用**//
  R_PORT3->PODR_b.PODR4 = d      ;          //
  R_PORT3->PODR_b.PODR3 = d >> 1 ;          //
  R_PORT1->PODR_b.PODR5 = d >> 2 ;          //
  R_PORT1->PODR_b.PODR4 = d >> 3 ;          //
  R_PORT1->PODR_b.PODR3 = d >> 4 ;          //
  R_PORT1->PODR_b.PODR2 = d >> 5 ;          //
  R_PORT1->PODR_b.PODR6 = d >> 6 ;          //
  R_PORT1->PODR_b.PODR7 = d >> 7 ;          //
//////////////////////////////////////////////

//**Arduino UNO R4 WiFi ではこちらを使用**//
  R_PORT3->PODR_b.PODR4  = d      ;       //
  R_PORT3->PODR_b.PODR3  = d >> 1 ;       //
  R_PORT1->PODR_b.PODR4  = d >> 2 ;       //
  R_PORT1->PODR_b.PODR5  = d >> 3 ;       //
  R_PORT1->PODR_b.PODR6  = d >> 4 ;       //
  R_PORT1->PODR_b.PODR7  = d >> 5 ;       //
  R_PORT1->PODR_b.PODR11 = d >> 6 ;       //
  R_PORT1->PODR_b.PODR12 = d >> 7 ;       //
////////////////////////////////////////////

  R_PORT0->PODR_b.PODR0 = 0;
  R_PORT0->PODR_b.PODR0 = 1;
}

void Lcd_Write_Com(unsigned char VH)  
{   
  R_PORT0->PODR_b.PODR1 = 0;
  Lcd_Writ_Bus(VH);
}

void Lcd_Write_Data(unsigned char VH)
{
  R_PORT0->PODR_b.PODR1 = 1;
  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)
{
  R_PORT1->PODR_b.PODR1 = 1;
  delay(5); 
  R_PORT1->PODR_b.PODR1 = 0;
  delay(15);
  R_PORT1->PODR_b.PODR1 = 1;
  delay(15);

  R_PORT0->PODR_b.PODR2 = 1;
  R_PORT0->PODR_b.PODR0 = 1;
  R_PORT0->PODR_b.PODR2 = 0;

  Lcd_Write_Com(0xCB);  
  Lcd_Write_Data(0x39); 
  Lcd_Write_Data(0x2C); 
  Lcd_Write_Data(0x00); 
  Lcd_Write_Data(0x34); 
  Lcd_Write_Data(0x02); 

  Lcd_Write_Com(0xCF);  
  Lcd_Write_Data(0x00); 
  Lcd_Write_Data(0XC1); 
  Lcd_Write_Data(0X30); 

  Lcd_Write_Com(0xE8);  
  Lcd_Write_Data(0x85); 
  Lcd_Write_Data(0x00); 
  Lcd_Write_Data(0x78); 

  Lcd_Write_Com(0xEA);  
  Lcd_Write_Data(0x00); 
  Lcd_Write_Data(0x00); 
 
  Lcd_Write_Com(0xED);  
  Lcd_Write_Data(0x64); 
  Lcd_Write_Data(0x03); 
  Lcd_Write_Data(0X12); 
  Lcd_Write_Data(0X81); 

  Lcd_Write_Com(0xF7);  
  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(0x2b);   //Contrast
  Lcd_Write_Data(0x2b); 
 
  Lcd_Write_Com(0xC7);    //VCM control2 
  Lcd_Write_Data(0xc0);   //--
 
  Lcd_Write_Com(0x36);    // Memory Access Control 
  Lcd_Write_Data(0x30);   

  Lcd_Write_Com(0x21);    //Display Inversion ON

  Lcd_Write_Com(0x3A);    
  Lcd_Write_Data(0x66); 

  Lcd_Write_Com(0xB1);    
  Lcd_Write_Data(0x00);  
  Lcd_Write_Data(0x1b); 
 
  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 
  Lcd_Write_Com(0x2c); 

}

void setup() {
  Serial.begin(115200);
  while (!Serial); //シリアルモニター開くまで待ち

  R_PORT0->PDR |= 0x4007;
  R_PORT1->PDR |= 0x18ff;
  R_PORT3->PDR |= 0x0018;

  R_PORT0->PODR_b.PODR14 = 1;
  R_PORT0->PODR_b.PODR0 = 1;
  R_PORT0->PODR_b.PODR1 = 1;
  R_PORT0->PODR_b.PODR2 = 1;
  R_PORT1->PODR_b.PODR1 = 1;

  Lcd_Init();

  //SDカードInit
  Serial.print("Initializing SD card...");
  if (!SD.begin(SDCS)) { // Initialization of SD card
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  SD_ViewFileList();  //ファイル一覧表示
}

void loop() {
  long getNum;

  while(!Serial.available()); //シリアルモニターで入力待ち
  getNum = Serial.parseInt();
  if(getNum == 0)
    return;
  if(getNum > filecount)
    return;
  SD_GetFileName(getNum);  //選択したJpegファイルのファイル名取得

  //Jpegファイルオープン
  File jpgFile = SD.open(filename, FILE_READ);
  JpegDec.decodeSdFile(jpgFile);

  //Jpegファイル情報表示
  Serial.print("File Name :");
  Serial.println(filename);
  Serial.print("Width     :");
  Serial.println(JpegDec.width);
  Serial.print("Height    :");
  Serial.println(JpegDec.height);
  Serial.print("Components:");
  Serial.println(JpegDec.comps);
  Serial.print("MCU / row :");
  Serial.println(JpegDec.MCUSPerRow);
  Serial.print("MCU / col :");
  Serial.println(JpegDec.MCUSPerCol);
  Serial.print("Scan type :");
  Serial.println(JpegDec.scanType);
  Serial.print("MCU width :");
  Serial.println(JpegDec.MCUWidth);
  Serial.print("MCU height:");
  Serial.println(JpegDec.MCUHeight);
  Serial.println("");

  drowJpeg();  //Jpeg画像を表示
  jpgFile.close();
  SD_ViewFileList();  //ファイル一覧表示
}

void SD_ViewFileList(void)
{
  File root = SD.open("/");
  filecount = 1;
  while (true) {
    File entry =  root.openNextFile();
    if (! entry)
      break;
    Serial.print(filecount);
    Serial.print(" : ");
    Serial.println(entry.name());
    filecount++;
    entry.close();
  }
  Serial.println("");
  root.close();
  filecount--;
}

void SD_GetFileName(int gn)
{
  File root, entry;
  root = SD.open("/");
  for(int i1 = 0; i1 < gn; i1++)
    entry =  root.openNextFile();
  strcpy(filename, entry.name());
  entry.close();
  root.close();
}

void drowJpeg(void){
  unsigned long i1;;
  uint16_t *pImg;
  int bx, by;

  //液晶ディスプレイ消去
  R_PORT0->PODR_b.PODR2 = 0;
  Address_set(0, 0, 319, 239);
  for(i1 = 0; i1 < 76800; i1++){
    Lcd_Write_Data(0);
    Lcd_Write_Data(0);
    Lcd_Write_Data(0);
  }
  R_PORT0->PODR_b.PODR2 = 1;

  //画像データ ディスプレイ転送
  R_PORT0->PODR_b.PODR2 = 0;
  while(JpegDec.read()){
    pImg = JpegDec.pImage ;
    Address_set(JpegDec.MCUx * JpegDec.MCUWidth,
                JpegDec.MCUy * JpegDec.MCUHeight,
                JpegDec.MCUx * JpegDec.MCUWidth + JpegDec.MCUWidth - 1,
                JpegDec.MCUy * JpegDec.MCUHeight + JpegDec.MCUHeight - 1);
    for(bx = 0; bx < JpegDec.MCUWidth; bx++){
      for(by = 0; by < JpegDec.MCUHeight; by++){
        Lcd_Write_Data(*pImg << 3); //R
        Lcd_Write_Data(*pImg >> 3); //G
        Lcd_Write_Data(*pImg >> 8); //B
        pImg += JpegDec.comps ;
      }
    }
  }
  R_PORT0->PODR_b.PODR2 = 1;
}