02.picoでTouch displayデモ C言語


02.picoでTouch displayデモ C言語

picoでタッチディスプレイの動作デモ

ディスプレイはPico-ResTouch-LCD-3.5 (Waveshare)
https://www.waveshare.com/wiki/Pico-ResTouch-LCD-3.5

で、購入先は、WAVESHARE-19907(SWサイエンス)です。
https://www.switch-science.com/catalog/7330/

・型名:Pico-ResTouch-LCD-3.5
・ブランド: Waveshare (微雪電子)
・Raspberry Pi Pico用ソケット付
・microSDカードスロット付
・リセットSW付(picoの30番pin RUNをGNDに落とす)
・動作電圧:5V
・解像度:480x320ピクセル
・通信:4線式SPI
・ディスプレイサイズ:73x49mm 3.5インチ
・ピクセルサイズ:0.153x0.153mm
・ディスプレイパネル:IPS 65k色
・モニタドライバー:ILI9488(ILITEK)
・抵抗膜方式タッチコントローラー:XPT2046 (xptek)
・バックライト電源:CAT6219(ON Semi)降圧0.5A
・リニア電圧レギュレータ:RT9193-33(ミツミ)VSYSから3.3V0.3Aを作成
・クロック周波数カウンタ:74HC4040 12bit非同期バイナリカウンタ
・インバーター:74HC04D 2~6Vインバーターx6
・シリアル-パラレル変換:74HC4094
・プログラム可能なバックライト制御(コメント文になっている)

使用pin

* GP5,8-13,15-22の15pin使用
VCC VSYS 電源入力
GND GND
GP5 SD クロック入力 SCK
GP8 LCD データ(H)/コマンド(L)
GP9 LCD チップセレクト(ローアクティブ)
GP10 LCD CLK
GP11 SPI MOSI
GP12 SPI MISO
GP13 LCD バックライト制御
GP15 LCD リセット(ローアクティブ)
GP16 Touch チップセレクト(ローアクティブ)
GP17 Touch 割込み(ローアクティブ)
GP18 SD CMD
GP19 SD D0
GP20 SD D1
GP21 SD D2
GP22 SD CS/D3

デモコード

https://www.waveshare.com/w/upload/f/fc/Pico-ResTouch-LCD-X_X_Code.zip
C:\Pico\touch1にダウンロードしたCフォルダの中身をコピーし、前回と同様にビルドすると簡単に動作します。コードは一部変更しました。
FAT形式でフォーマットしたマイクロSDのルートに 480x320 24ビットのBMPファイルが必要です。

GUI_Show 図形や文字列の表示
GUI_Clear 緑画面
LCD_Show_bmp 写真1
LCD_Show_bmp 写真2
TP_DrawBoard タッチパッド

C:\Pico\touch1\examples\lcd_test.c

関数は、デモコードのlibホルダ内で設定しています。
メインの関数は
・GUI_Show (直線、四角、円、文字列の表示)
・LCD_Show_bmp (SDのbmp画像表示)
・TP_DrawBoard (タッチパッドの表示 ループ)
で、マイクロSDに保存する画像は
FAT形式, 480x320, 24ビットBMP, ルートに保存

// lcd_test.c (Waveshare team)
#include "main.h"
#include "LCD_Driver.h"
#include "LCD_Touch.h"
#include "LCD_GUI.h"
#include "LCD_Bmp.h"
#include "DEV_Config.h"
#include 
#include "hardware/watchdog.h"
#include "pico/stdlib.h"

int lcd_test(void){
  //uint8_t counter = 0;//無くても動作
  System_Init();      //GPIO,SPI,LCD等初期化
  SD_Init();          //SDカード初期化
  LCD_SCAN_DIR  lcd_scan_dir = SCAN_DIR_DFT; //スキャンモードを設定
  LCD_Init(lcd_scan_dir,200);//LCDパネルを初期化、スキャンモードと明るさ確認 バックライト可変出来ない PWMがコメントになっている
  TP_Init(lcd_scan_dir);//パネル初期化  スキャンモードを設定
  GUI_Show();              //オリンピックマーク等表示 lib\lcd\LCD_GUI.c参照
  Driver_Delay_ms(2000);   //2秒待つ
  GUI_Clear(0xf800);       //1面赤
  Driver_Delay_ms(1000);   //1秒待つ
  GUI_Clear(0x07e0);       //1面緑
  Driver_Delay_ms(1000);   //1秒待つ
  GUI_Clear(0x001f);       //1面青
  Driver_Delay_ms(1000);   //1秒待つ
  LCD_SCAN_DIR bmp_scan_dir = D2U_R2L; //
  LCD_Show_bmp(bmp_scan_dir,lcd_scan_dir); // SDのBMPを表示
  TP_GetAdFac();           //表示調整
  TP_Dialog();             //パネルクリア
  while(1){                //永久ループ
    TP_DrawBoard();  //タッチパッドを表示 LCD_Touch.c参照
  }
  return 0;
}

C:\Pico\touch1\lib\lcd\LCD_GUI.cの一部


void GUI_Show(void){
  //DEBUG("LCD_Dis_Column = %d\r\n", sLCD_DIS.LCD_Dis_Column);
  //DEBUG("LCD_Dis_Page = %d\r\n", sLCD_DIS.LCD_Dis_Page);
  GUI_Clear(WHITE);//画面クリア(白)
  //DEBUG("Draw Line\r\n");
  GUI_DrawLine(0, 10, LCD_3_5_WIDTH, 10, RED, LINE_SOLID, DOT_PIXEL_2X2);//横赤太線
  GUI_DrawLine(0, 20, LCD_3_5_WIDTH, 20, RED, LINE_DOTTED, DOT_PIXEL_DFT);//横赤点線
  GUI_DrawLine(0, 300, LCD_3_5_WIDTH, 300, RED, LINE_DOTTED, DOT_PIXEL_DFT);//横赤点線
  GUI_DrawLine(0, 310, LCD_3_5_WIDTH, 310, RED, LINE_SOLID, DOT_PIXEL_2X2);//横赤太線
  //DEBUG("Draw Rectangle\r\n");
  GUI_DrawRectangle(10, 30, sLCD_DIS.LCD_Dis_Column - 10, sLCD_DIS.LCD_Dis_Page - 30, BLUE, DRAW_EMPTY, DOT_PIXEL_DFT);//青枠
  GUI_DrawRectangle(20, 40, sLCD_DIS.LCD_Dis_Column - 20, 60, BLUE, DRAW_FULL, DOT_PIXEL_DFT);//青四角
  //DEBUG("Draw Olympic Rings\r\n");
  uint16_t Cx1 = 190, Cy1 = 240, Cr = 20;
  uint16_t Cx2 = Cx1 + (2.5 * Cr), Cy2 = Cy1;
  uint16_t Cx3 = Cx1 + (5 * Cr), Cy3 = Cy1;
  uint16_t Cx4 = ( Cx1 + Cx2 ) / 2, Cy4 = Cy1 + Cr;
  uint16_t Cx5 = ( Cx2 + Cx3 ) / 2, Cy5 = Cy1 + Cr;
  GUI_DrawCircle( Cx1, Cy1, Cr, BLUE, DRAW_EMPTY, DOT_PIXEL_2X2);//青枠丸
  GUI_DrawCircle( Cx2, Cy2, Cr, BLACK, DRAW_EMPTY, DOT_PIXEL_2X2);//黒枠丸
  GUI_DrawCircle( Cx3, Cy3, Cr, RED, DRAW_EMPTY, DOT_PIXEL_2X2);//赤枠丸
  GUI_DrawCircle( Cx4, Cy4, Cr, YELLOW, DRAW_EMPTY, DOT_PIXEL_2X2);//黄枠丸
  GUI_DrawCircle( Cx5, Cy5, Cr, GREEN, DRAW_EMPTY, DOT_PIXEL_2X2);//(黄)緑枠丸
  //DEBUG("Draw Realistic circles\r\n");
  GUI_DrawCircle(50, 250, 30, CYAN, DRAW_FULL, DOT_PIXEL_DFT);//水色丸
  GUI_DrawCircle(sLCD_DIS.LCD_Dis_Column - 50, 250, 30, CYAN, DRAW_FULL, DOT_PIXEL_DFT);//水色丸
  //DEBUG("Display String\r\n");
  GUI_DisString_EN(80, 80, "WaveShare Electronic", &Font24, LCD_BACKGROUND, BLUE);//青字 サイズ24(max)
  GUI_DisString_EN(80, 120, "3.5inch TFTLCD", &Font20, RED, BLUE);//赤地青字 サイズ20
  //DEBUG("Display Nummber\r\n");
  GUI_DisNum(80, 150, 1234567890, &Font16, LCD_BACKGROUND, BLUE);//青数値16
}

C:\Pico\touch1\lib\lcd\LCD_Bmp.cの一部


/********************************************************************************
parameter: 
		Bmp_ScanDir :   Displays the LCD scanning mode of the BMP picture
		Lcd_ScanDir :   LCD normal display scan
********************************************************************************/
void LCD_Show_bmp(LCD_SCAN_DIR Bmp_ScanDir, LCD_SCAN_DIR Lcd_ScanDir){
	uint32_t bmplen = 0x00;
    uint32_t checkstatus = 0x00;
    uint32_t filesnumbers = 0x00;
    uint32_t bmpcounter = 0x00;
    DIR directory;
    FRESULT res;
    /* ディレクトリを開く */
	LCD_Clear(LCD_BACKGROUND);
    res = f_opendir(&directory, "/");
    if((res != FR_OK)){
		if(res == FR_NO_FILESYSTEM){			
			GUI_DisString_EN(0, 32, "SD_CARD_NOT_FORMATTED", &Font24,LCD_BACKGROUND,BLUE);//SDがFAT形式でない
		}else{
			GUI_DisString_EN(0, 48, "SD_CARD_OPEN_FAIL", &Font24,LCD_BACKGROUND,BLUE);//ディレクトリを開けない
		}
	}
    filesnumbers = Storage_GetDirectoryBitmapFiles ("/", pDirectoryFiles);//BMPファイルの数を取得
    bmpcounter = 1;//最初の画像を表示 BMPカウンターを設定
	int showtime;
    for(showtime = 0; showtime < filesnumbers ; showtime++){
        sprintf((char*)str, "%-11.11s", pDirectoryFiles[bmpcounter -1]);
        checkstatus = Storage_CheckBitmapFile((const char*)str, &bmplen);
        if(checkstatus == 0){
			LCD_SetGramScanWay(Bmp_ScanDir);//画像のスキャンを表示
      
			Storage_OpenReadFile(0, 0, (const char*)str);//画像を表示
        }else if (checkstatus == 1){
			/* メッセージを表示:SDカードが存在しません */
			//デフォルトのスキャンを復元します
			LCD_SetGramScanWay( Lcd_ScanDir );
			GUI_DisString_EN(0, 64, "SD_CARD_NOT_FOUND", &Font24,LCD_BACKGROUND,BLUE);
        }else {
			/* メッセージの表示:ファイルはサポートされていません */
			//デフォルトのスキャンを復元します
			LCD_SetGramScanWay( Lcd_ScanDir );
            GUI_DisString_EN(0, 80, "SD_CARD_FILE_NOT_SUPPORTED", &Font24,LCD_BACKGROUND,BLUE);
        }
        bmpcounter ++;
        if(bmpcounter > filesnumbers){
			bmpcounter = 1;
			break;
        }
	}
	LCD_Clear(LCD_BACKGROUND);
	//デフォルトのスキャンを復元します
	LCD_SetGramScanWay( Lcd_ScanDir );
	DEV_Digital_Write(SD_CS_PIN,1);	
}

C:\Pico\touch1\lib\lcd\LCD_Touch.cの一部


/*****************************************************************************
function:
		Draw Board タッチパッド
ADボタン:画面の指示に従って赤い+記号をクリックして画面を調整
クリアボタン(右上隅):タッチパッドをクリア
デフォルトで4セットのキャリブレーション値を使用
5色の選択(右側) デフォルトは黒
ブラシサイズ:9ピクセル(デフォルト)
*******************************************************************************/
void TP_DrawBoard(void){
  TP_Scan(0);
  if (sTP_DEV.chStatus & TP_PRESS_DOWN) {		//Press the button
      //Horizontal screen
      if (sTP_Draw.Xpoint < sLCD_DIS.LCD_Dis_Column &&
          //Determine whether the law is legal
          sTP_Draw.Ypoint < sLCD_DIS.LCD_Dis_Page) {
      //Judgment is horizontal screen
      if(sLCD_DIS.LCD_Dis_Column > sLCD_DIS.LCD_Dis_Page) {
        printf("horizontal x:%d,y:%d\n",sTP_Draw.Xpoint,sTP_Draw.Ypoint);
        if (sTP_Draw.Xpoint > (sLCD_DIS.LCD_Dis_Column - 60) &&
          sTP_Draw.Ypoint < 16) {		//Clear Board
          TP_Dialog();
        } else if(sTP_Draw.Xpoint > (sLCD_DIS.LCD_Dis_Column - 120) &&
              sTP_Draw.Xpoint < (sLCD_DIS.LCD_Dis_Column - 80) &&
              sTP_Draw.Ypoint < 24) { //afresh adjustment
          TP_Adjust();
          TP_Dialog();
        } else if(sTP_Draw.Xpoint > (sLCD_DIS.LCD_Dis_Column - 50) &&
              sTP_Draw.Xpoint < sLCD_DIS.LCD_Dis_Column &&
              sTP_Draw.Ypoint > 20 &&
              sTP_Draw.Ypoint < 70) {
          sTP_Draw.Color = BLUE;
        } else if(sTP_Draw.Xpoint > (sLCD_DIS.LCD_Dis_Column - 50) &&
              sTP_Draw.Xpoint < sLCD_DIS.LCD_Dis_Column &&
              sTP_Draw.Ypoint > 80 &&
              sTP_Draw.Ypoint < 130) {
          sTP_Draw.Color = GREEN;
        } else if(sTP_Draw.Xpoint > (sLCD_DIS.LCD_Dis_Column - 50) &&
              sTP_Draw.Xpoint < sLCD_DIS.LCD_Dis_Column &&
              sTP_Draw.Ypoint > 140 &&
              sTP_Draw.Ypoint < 190) {
          sTP_Draw.Color = RED;
        } else if(sTP_Draw.Xpoint > (sLCD_DIS.LCD_Dis_Column - 50) &&
              sTP_Draw.Xpoint < sLCD_DIS.LCD_Dis_Column &&
              sTP_Draw.Ypoint > 200 && sTP_Draw.Ypoint < 250) {
          sTP_Draw.Color = YELLOW;
        } else if(sTP_Draw.Xpoint > (sLCD_DIS.LCD_Dis_Column - 50) &&
              sTP_Draw.Xpoint < sLCD_DIS.LCD_Dis_Column &&
              sTP_Draw.Ypoint > 260 &&
              sTP_Draw.Ypoint < 310) {
          sTP_Draw.Color = BLACK;
        } else {
          GUI_DrawPoint(sTP_Draw.Xpoint, sTP_Draw.Ypoint,
                  sTP_Draw.Color , DOT_PIXEL_1X1, DOT_FILL_RIGHTUP);
          GUI_DrawPoint(sTP_Draw.Xpoint + 1, sTP_Draw.Ypoint,
                  sTP_Draw.Color , DOT_PIXEL_1X1, DOT_FILL_RIGHTUP);
          GUI_DrawPoint(sTP_Draw.Xpoint, sTP_Draw.Ypoint + 1,
                  sTP_Draw.Color , DOT_PIXEL_1X1, DOT_FILL_RIGHTUP);
          GUI_DrawPoint(sTP_Draw.Xpoint + 1, sTP_Draw.Ypoint + 1,
                  sTP_Draw.Color , DOT_PIXEL_1X1, DOT_FILL_RIGHTUP);
          GUI_DrawPoint(sTP_Draw.Xpoint, sTP_Draw.Ypoint,
                  sTP_Draw.Color , DOT_PIXEL_2X2, DOT_FILL_RIGHTUP);
        }
        //Vertical screen
      } else {
        printf("Vertical x:%d,y:%d\n",sTP_Draw.Xpoint,sTP_Draw.Ypoint);
        if (sTP_Draw.Xpoint > (sLCD_DIS.LCD_Dis_Column - 60) &&
          sTP_Draw.Ypoint < 16) {//Clear Board
          TP_Dialog();
        } else if(sTP_Draw.Xpoint > (sLCD_DIS.LCD_Dis_Column - 120) &&
              sTP_Draw.Xpoint < (sLCD_DIS.LCD_Dis_Column - 80) &&
              sTP_Draw.Ypoint < 24) { //afresh adjustment
          TP_Adjust();
          TP_Dialog();
        } else if(sTP_Draw.Xpoint > 20 && sTP_Draw.Xpoint < 70 &&
              sTP_Draw.Ypoint > 20 && sTP_Draw.Ypoint < 70) {
          sTP_Draw.Color = BLUE;
        } else if(sTP_Draw.Xpoint > 80 && sTP_Draw.Xpoint < 130 &&
              sTP_Draw.Ypoint > 20 && sTP_Draw.Ypoint < 70) {
          sTP_Draw.Color = GREEN;
        } else if(sTP_Draw.Xpoint > 140 && sTP_Draw.Xpoint < 190 &&
              sTP_Draw.Ypoint > 20 && sTP_Draw.Ypoint < 70) {
          sTP_Draw.Color = RED;
        } else if(sTP_Draw.Xpoint > 200 && sTP_Draw.Xpoint < 250 &&
              sTP_Draw.Ypoint > 20 && sTP_Draw.Ypoint < 70) {
          sTP_Draw.Color = YELLOW;
        } else if(sTP_Draw.Xpoint > 260 && sTP_Draw.Xpoint < 310 &&
              sTP_Draw.Ypoint > 20 && sTP_Draw.Ypoint < 70) {
          sTP_Draw.Color = BLACK;
        } else {
          GUI_DrawPoint(sTP_Draw.Xpoint, sTP_Draw.Ypoint,
                  sTP_Draw.Color , DOT_PIXEL_2X2,
                  DOT_FILL_RIGHTUP );
        }
      }
      }
  }
}