/**************************************************************** * ビットマップファイル表示実験プログラム2:PIC32MX_BMP_TEST_2.c * * <このTESTの目的> *  @ SDカードに収録されているBMPファイル(128*64ドット)を読出し *   同じ解像度のモノクロ液晶全面に、そのイメージを表示する。 *  A 表示方式は、ピクセル描画関数を使って、横方向に1ドットずつ描画する。 *    簡単な方法から、新たに、イメージ描画関数を作成し、ライト関数のみ *    を使って、最下段より、縦方向に8ドット単位で描画する方法に変更してみる。 *    これによって、描画時間の短縮が期待できるので、どの程度改善されるか *    実測にて確認してみる。 * * * 簡易テストなので、SWで、次のファイルをサーチする機能は無しにした。 * 但し、SDに収録されている、BMPファイルの、順次繰返し描画は可能にした。 * * 実験ハードは、以前製作した、ファイルリスト表示形式の、SD_MIDプレーヤを流用 * * ファイルシステム:MMD File System→ FAT16(FAT32互換) * Graphic LCD(Monochrome): SG12864A * * Condition: * 8MHz External X'tal Oscillator, 20x PLL (8MHzx20= 160MHz) * Fcy=160MHz/2=80MHz, Tcy=12.5ns * * CPU: PIC32MX340F256H * * N.Ishii 2014.10.13 * <修正履歴> * 141017 * Conv_BMP_DataTable関数の、頭で、Disp_BUFを全クリアしているが * 必要ないので削除(コメントアウト)した。 *******************************************************************/ #include /* PIC32 peripheral library */ #include "glcd_lib32k.h" #include // コンフィギュレーション設定 // CPU=80MHz Peri=80MHz,HS+PLL,Divider=1/2,PLL=x20,WDT=Off #pragma config FNOSC=PRIPLL, POSCMOD=HS, FPLLIDIV=DIV_2 #pragma config FPLLMUL=MUL_20, FPBDIV=DIV_1, FPLLODIV=DIV_1 #pragma config FWDTEN=OFF, ICESEL=ICS_PGx2 /// ファイルシステム用変数 FSFILE *fptr; size_t result; SearchRec Record; SearchRec *rptr = &Record; /// データバッファ unsigned char Buffer[1024]; // 元になる、BMPデータバッファ unsigned char Disp_BUF[1024]; // 表示用のデータバッファ /// グローバル変数 short i; /// Prototyping void lcd_Image2(char *ptr); void Conv_BMP_DataTable(void); /******* メインルーチン ***********/ int main(void) { //システム最適設定 SYSTEMConfigPerformance(80000000); mJTAGPortEnable(DEBUG_JTAGPORT_OFF); // JTAGを無効化 //I/O設定 AD1PCFG = 0xFFFE; // デジタルに // GLCD制御信号レベルの初期化 LCD_E = 0; LCD_CS1 = 1; LCD_CS2 = 1; LCD_RW = 1; LCD_DI = 1; LCD_TRIS = 0x0000; // LCDデータバス(DB0-DB7)オール出力(TRISE= 0) ///// ポート設定は、SD_MIDプレーヤのハードを流用するので、そのハードの設定のままにしてある。(今回は、SW未使用、VS1053b未使用) TRISD = 0x0F00; // SW2:SEL_SW,SW3:ENT_SW,未使用SW(SW4,SW5):入力 // LCD_CS1,CS2,RS:出力・デバッグLED:出力、他未使用ピンは出力設定 TRISF = 0x0034; // VS1053b_SCK1,SDO:出力、SDI1:入力・ LCD_E,RW:出力、他未使用ピンは入力設定 TRISG = 0x028C; // SD_SDO,SCK:出力、SDI:入力・他未使用ピンは入力設定 TRISB = 0x4FDF; // VS1053b_CS,RESET,DCS:出力、DREQ:入力・SD_CS:出力、WE,CD:入力、他未使用ピンは入力設定 CNPUE = 0x0060; // SD_CD(CN5),WE(CN6)のみ内部プルアップ LATDbits.LATD3 = 1; // デバッグLED消灯 // 液晶表示器の初期化 lcd_Init(); lcd_Clear(0); // 画面消去 LATDbits.LATD3 = 1; // デバッグLED消灯 /// カード挿入まで待ちファイル有無確認 while(fptr == 0){ lcd_Clear(0); // 画面消去 if(!MDD_MediaDetect()){ // カード挿入中か? lcd_Str(0, 0, "Wait Card Insert!"); // 挿入待ちメッセージ } else{ /*** ファイルオープンとファイル名表示 ***/ lcd_Str(0, 0, "Find Card OK! "); FSInit(); // FS初期化 /* 最初のファイルのサーチ */ result = FindFirst("*.BMP", ATTR_ARCHIVE, rptr); if(result != 0){ // BMPファイルありか? lcd_Str(0, 0, "Find No File? "); // ファイル無しメッセージ } else break; // ファイル発見で抜ける } delay_ms(500); // 0.5秒ごとに繰り返し } ////// ファイルが発見できた場合の処理 delay_ms(500); lcd_Str(1, 0, Record.filename); // ファイル名表示 delay_ms(1000); lcd_Clear(0); // 画面消去 fptr = FSfopen(Record.filename, "r"); // File Open (Read Mode) /************* メインループ ****************/ while(1) { if(fptr != 0){ // ファイルオープンに成功の場合、以下を実行 FSfread(Buffer,1,62,fptr); // ヘッダ情報部の、規定バイト数:62バイト分は、読み飛ばす FSfread(Buffer,1,1024,fptr); // 元BMPデータを、バッファへ全て(1024バイト)転送 for(i= 0; i< 1024; i++) Buffer[i]= ~Buffer[i]; // データ論理反転して入れ替え Conv_BMP_DataTable(); // 元BMPデータ配列を、表示用の配列に変換 lcd_Image2(Disp_BUF); // 最下段からイメージ描画する FSfclose(fptr); // イメージ描画が終了したら、ファイルをクローズ delay_ms(2000); // 2秒間表示 lcd_Clear(0); // 画面消去 /// 次の、BMPファイルをサーチし、繰返す result = FindNext(rptr); // To Next File if ((result==0) && (Record.attributes == ATTR_ARCHIVE)) // 次の、BMPファイルが見つかったら、オープン fptr = FSfopen(Record.filename, "r"); else { // 次の、BMPファイルが見つからなかったら、最初のファイルをサーチして繰返す result = FindFirst("*.BMP", ATTR_ARCHIVE, rptr); if (result == 0) { fptr = FSfopen(Record.filename, "r"); // File Open (Read Mode) } } lcd_Str(1, 0, Record.filename); // ファイル名表示 delay_ms(1000); lcd_Clear(0); // 画面消去 } } } /********************************************************************** * 元BMPデータ配列を、表示用の配列に変換 ***********************************************************************/ void Conv_BMP_DataTable(void) { short i; // 元BMPデータバッファ:Buffer[*]の、ポインタ short j; // 表示用データバッファ:Disp_BUF[*]の、ポインタ /* //// このクリアは、不要なのでコメントアウトした  141017 /// 表示バッファ全エリアクリア for(j= 0; j< 1024; j++){ Disp_BUF[j]= 0; } */ /// 各バッファのポインタを、最初の開始位置に初期化 i= 0; j= 0; do{ /// 8 x 8ビットブロックの配列変換(横8ビット配列を、縦8ビット配列に変換)------ Disp_BUF[j+0]= (Buffer[i+0] & 0x80) | (Buffer[i+16] & 0x80)>> 1 | (Buffer[i+32] & 0x80)>> 2 | (Buffer[i+48] & 0x80)>> 3 | (Buffer[i+64] & 0x80)>> 4 | (Buffer[i+80] & 0x80)>> 5 | (Buffer[i+96] & 0x80)>> 6 | (Buffer[i+112] & 0x80)>> 7; Disp_BUF[j+1]= (Buffer[i+0] & 0x40)<< 1 | (Buffer[i+16] & 0x40) | (Buffer[i+32] & 0x40)>> 1 | (Buffer[i+48] & 0x40)>> 2 | (Buffer[i+64] & 0x40)>> 3 | (Buffer[i+80] & 0x40)>> 4 | (Buffer[i+96] & 0x40)>> 5 | (Buffer[i+112] & 0x40)>> 6; Disp_BUF[j+2]= (Buffer[i+0] & 0x20)<< 2 | (Buffer[i+16] & 0x20)<< 1 | (Buffer[i+32] & 0x20) | (Buffer[i+48] & 0x20)>> 1 | (Buffer[i+64] & 0x20)>> 2 | (Buffer[i+80] & 0x20)>> 3 | (Buffer[i+96] & 0x20)>> 4 | (Buffer[i+112] & 0x20)>> 5; Disp_BUF[j+3]= (Buffer[i+0] & 0x10)<< 3 | (Buffer[i+16] & 0x10)<< 2 | (Buffer[i+32] & 0x10)<< 1 | (Buffer[i+48] & 0x10) | (Buffer[i+64] & 0x10)>> 1 | (Buffer[i+80] & 0x10)>> 2 | (Buffer[i+96] & 0x10)>> 3 | (Buffer[i+112] & 0x10)>> 4; Disp_BUF[j+4]= (Buffer[i+0] & 0x08)<< 4 | (Buffer[i+16] & 0x08)<< 3 | (Buffer[i+32] & 0x08)<< 2 | (Buffer[i+48] & 0x08)<< 1 | (Buffer[i+64] & 0x08) | (Buffer[i+80] & 0x08)>> 1 | (Buffer[i+96] & 0x08)>> 2 | (Buffer[i+112] & 0x08)>> 3; Disp_BUF[j+5]= (Buffer[i+0] & 0x04)<< 5 | (Buffer[i+16] & 0x04)<< 4 | (Buffer[i+32] & 0x04)<< 3 | (Buffer[i+48] & 0x04)<< 2 | (Buffer[i+64] & 0x04)<< 1 | (Buffer[i+80] & 0x04) | (Buffer[i+96] & 0x04)>> 1 | (Buffer[i+112] & 0x04)>> 2; Disp_BUF[j+6]= (Buffer[i+0] & 0x02)<< 6 | (Buffer[i+16] & 0x02)<< 5 | (Buffer[i+32] & 0x02)<< 4 | (Buffer[i+48] & 0x02)<< 3 | (Buffer[i+64] & 0x02)<< 2 | (Buffer[i+80] & 0x02)<< 1 | (Buffer[i+96] & 0x02) | (Buffer[i+112] & 0x02)>> 1; Disp_BUF[j+7]= (Buffer[i+0] & 0x01)<< 7 | (Buffer[i+16] & 0x01)<< 6 | (Buffer[i+32] & 0x01)<< 5 | (Buffer[i+48] & 0x01)<< 4 | (Buffer[i+64] & 0x01)<< 3 | (Buffer[i+80] & 0x01)<< 2 | (Buffer[i+96] & 0x01)<< 1 | (Buffer[i+112] & 0x01); ///----------------------------------------------------------------------------- j+= 8; // 次の、8 x 8ビットブロックの、Disp_BUF[*]の、開始位置に移動 i++; // 次の、8 x 8ビットブロックの、Buffer[*]の、開始位置に移動 if(i == 16) i= 128; // 最下段(page7相当)の、16ブロック分の変換が終了したら、次の上段(page6相当)の、開始位置に移動 if(i == 144) i= 256; // page6相当の、16ブロック分の変換が終了したら、次の上段(page5相当)の、開始位置に移動 if(i == 272) i= 384; // page5相当の、16ブロック分の変換が終了したら、次の上段(page4相当)の、開始位置に移動 if(i == 400) i= 512; // page4相当の、16ブロック分の変換が終了したら、次の上段(page3相当)の、開始位置に移動 if(i == 528) i= 640; // page3相当の、16ブロック分の変換が終了したら、次の上段(page2相当)の、開始位置に移動 if(i == 656) i= 768; // page2相当の、16ブロック分の変換が終了したら、次の上段(page1相当)の、開始位置に移動 if(i == 784) i= 896; // page1相当の、16ブロック分の変換が終了したら、次の上段(page0相当)の、開始位置に移動 }while(i< 912); // 最後のブロックの、Buffer[*]の、開始位置は、911になるので、 // i= 912(全128ブロック:64ビット x 128=8192ビット=1024バイト) // で全エリアの変換が終了することになる } /******************************************************** * イメージ表示関数2 * * 後閑氏オリジナルの、lcd_Image関数は、最上段から描画 * しているが、最下段から描画する関数を、追加した。 * 標準のBMPイメージデータは、最下段のデータから配列さ * れているので、その方のが、都合がよい。 *********************************************************/ void lcd_Image2(char *ptr) { char cs, Xpos; short page, colum; for(page=7; page>=0; page--){ for(colum=0; colum<128; colum++){ if(colum > 63){ Xpos=colum-64; cs = 1; } else{ Xpos = colum; cs = 2; } lcd_Write(cs, 0xB8+page, 1); lcd_Write(cs, 0x40+Xpos, 1); lcd_Write(cs, *ptr++, 0); } } }