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; }