PICO LCD-1.8 (ST7735S)
Raspberry Pi Pico用 1.8インチ 液晶モジュール 160×128 (ST7735S) のArduinoIDEでの使用方法RaspberryPi PICOと連結して使用する設計になっているため、SPIピン(SLCK/MOSI)がGP10/GP11に固定になっていて変更できません。
ArduinoIDEでは(2022.02)現状、SPIピン(SLCK/MOSI)はGP2/GP3に固定になっており、普通の方法では、このLCDは使用できません。
1) 変換コネクタを使ってSPIピン(SLCK/MOSI)をGP2/GP3に変更する。
2) SoftwareSPIを使用する
3) ArduinoIDE以外の方法(Pythonとか)でプログラミング
の、いずれかの方法になります。

使用するピン
コネクタは40ピン付いていますが、実際に使用されているのは▼の8本です。| RaspberryPi PICOと合体して使用する場合 | ||
|---|---|---|
| 物理ピン番号 | 論理ピン名 | 機能 | 
| 11 | GP8 | Data/Command | 
| 12 | GP9 | Slave Selec | 
| 14 | GP10 | CLK | 
| 15 | GP11 | MOSI | 
| 16 | GP12 | Reset | 
| 17 | GP13 | BackLight | 
| 39 | VSYS | 1.8~5.5V | 
| 38 | GND | GND | 
| RaspberryPi PICO+ArduinoIDEで使用する場合 | ||
|---|---|---|
| 物理ピン番号 | 論理ピン名 | 機能 | 
| 11 | GP8 | Data/Command | 
| 12 | GP9 | Slave Selec | 
| 4 | GP2 | CLK | 
| 5 | GP3 | MOSI | 
| 16 | GP12 | Reset | 
| 17 | GP13 | BackLight | 
| 39 | VSYS | 1.8~5.5V | 
| 38 | GND | GND | 
GP10をGP2に、GP11をGP3に差し替えれば、ArduinoIDEで普通にSPIデバイスとして使用できます。
※ ▼はAdafruit_ST7735_and_ST7789_Libraryのサンプルスケッチを使用

ArduinoUNOでs使用する場合にはレベルシフターか抵抗を使って、信号レベルを3.3Vに落とした方が良い模様
| ArduinoUNOで使用する場合 | |
|---|---|
| 論理ピン名 | 機能 | 
| 任意 | Data/Command | 
| D10 ※変更可 | Slave Selec | 
| D13 | CLK | 
| D11 | MOSI | 
| 任意 | Reset | 
| 任意 | BackLight | 
| 5V | 5.0V | 
| GND | GND | 

ST7735Sのコマンド
コマンドは1バイトでパラメタは全てデータ扱いのため、コマンド送信時にはD/CをLOWに、パラメタ送信時にはD/CをHIGHにする。
| コマンド送信手順 | |
|---|---|
| SS(Slave Select) | LOWにする | 
| DC(Data/Command) | LOWにする | 
| コマンド送信 | |
| DC(Data/Command) | HIGHにする | 
| パラメタ送信 | |
| SS(Slave Select) | HIGHにする | 
▼ 必要最低限のコマンド。他にも色調整関連のコマンドが多数あります。詳細はST7735Sのスペックシート参照。
| コマンド | パラメタ | 動作 | 
|---|---|---|
| 0x01 | SOFTWARE RESET | |
| 0x11 | Sleep Out | |
| 0x13 | NomalDisplayMode | |
| 0x20 | Display Inversion Off | |
| 0x28 | Display OFF | |
| 0x29 | Display ON | |
| 0x36 | 1Byte | スキャン方向 | 
| 0x3A | 0x05 | 16Bit Pixel Mode | 
| 0xB4 | 0x00 | 表示色反転モード | 
| 0xB6 | 0x15,0x02 | フレームレート設定 | 
| コマンド | パラメタ | 動作 | 
| 0x2A | 開始X上位バイト、開始X下位バイト、終了X上位バイト、終了X下位バイト (0~159の範囲なので上位バイトは0固定で良い気がする) | Colmun Address | 
| 0x2B | 開始Y上位バイト、開始Y下位バイト、終了Y上位バイト、終了Y下位バイト (0~159の範囲なので上位バイトは0固定で良い気がする) | Row Address | 
| 0x2C | データ | BitmapData | 
描画モード設定コマンド Memory Data Access Control (0x36)
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
|---|---|---|---|---|---|---|---|---|
| コマンド | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 
| パラメタ | MY (Y軸方向) | MX (X軸方向) | MV (XY軸入れ替え) | ML (Y軸更新方向) | RGB (色割り当て RGB or BGR) | MH (X軸更新方向) | - | - | 
ML/RGB/MHは変更する必要はあまりないと思われる。
MY/MX/MVの組み合わせによる表示方向は▼のようになる

Dot指定方法設定コマンド Interface Pixel Format(0x3A)
1Dot(ピクセル)の色を指定する方法(フォーマット)を指定するこの指定で、描画コマンド Column Address Set (0x2A) のパラメタの意味が変わる
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
|---|---|---|---|---|---|---|---|---|
| コマンド | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 
| パラメタ | - | - | - | - | - | IFPF2 | IFPF1 | IFPF0 | 
| IFPF[2:0] | HEX | Color Format | 
|---|---|---|
| 011 | 3 | 12-bit/pixel | 
| 101 | 5 | 16-bit/pixel | 
| 110 | 6 | 18-bit/pixel | 
| 111 | 7 | No used | 

描画手順
描画範囲を指定し、指定範囲を埋めるBitmapデータを送信する| 描画範囲 COLの指定 | 0X2A | 0,XS,0,XE | 
|---|---|---|
| 描画範囲 ROWの指定 | 0x2B | 0,YS,0xYE | 
| 描画データ送信 | 0x2C | Bitmapデータ | 

 ST7753-PICO.zip (RaspberryPi PICO GP2/GP3使用)
 ST7753-PICO.zip (RaspberryPi PICO GP2/GP3使用) ST7753-UNO.zip (ArduinoUNO)
 ST7753-UNO.zip (ArduinoUNO) ST7753-SoftSPI.zip (RaspberryPi PICO SoftwareSPI GP10/GP11使用)
 ST7753-SoftSPI.zip (RaspberryPi PICO SoftwareSPI GP10/GP11使用)※ <>を全角<>に置き換えています。コピペの際は注意してください(ZIPファイルの解凍を推奨)。
#include <SPI.h>
#include "image2.h"
#include "font8x16.h"
#define TFT_CS  9    // Data/Command
#define TFT_DC  8    // Data/Command
#define TFT_RST 12   // RESET
#define TFT_BL  13   // BACK LIGHT
#define TFT_WIDTH 160
#define TFT_HIGH  128
uint8_t SPIBuf[256] ;   // SPI転送用バッファ
uint8_t fontColorF[2] ; // TEXT FOR GROND COLOR
uint8_t fontColorB[2] ; // TEXT BACK GROND COLOR
char str[64] ;
SPISettings settings = SPISettings(32000000, MSBFIRST, SPI_MODE0);
// TFTにコマンドを送信
void tftSendCommand(uint8_t command) {
  digitalWrite(TFT_CS, LOW); // 
  digitalWrite(TFT_DC, LOW); // Command mode
  SPI.transfer(command);
  digitalWrite(TFT_CS, HIGH);  //
}
// TFTにコマンド+1バイトデータを送信
void tftSendCommand1(uint8_t command, uint8_t data1) {
  digitalWrite(TFT_CS, LOW); // 
  digitalWrite(TFT_DC, LOW); // Command mode
  SPI.transfer(command);
  digitalWrite(TFT_DC, HIGH); // Command mode
  SPI.transfer(data1);
  digitalWrite(TFT_CS, HIGH);  //
}
// TFTにコマンド+2バイトデータを送信
void tftSendCommand2(uint8_t command, uint8_t data1, uint8_t data2) {
  digitalWrite(TFT_CS, LOW); // 
  digitalWrite(TFT_DC, LOW); // Command mode
  SPI.transfer(command);
  digitalWrite(TFT_DC, HIGH); // Command mode
  SPI.transfer(data1);
  SPI.transfer(data2);
  digitalWrite(TFT_CS, HIGH);  // 
}
// TFTにコマンド+3バイトデータを送信
void tftSendCommand3(uint8_t command, uint8_t data1, uint8_t data2, uint8_t data3) {
  digitalWrite(TFT_CS, LOW); // 
  digitalWrite(TFT_DC, LOW); // Command mode
  SPI.transfer(command);
  digitalWrite(TFT_DC, HIGH); // Command mode
  SPI.transfer(data1);
  SPI.transfer(data2);
  SPI.transfer(data3);
  digitalWrite(TFT_CS, HIGH);  //
}
// TFTにコマンド+4バイトデータを送信
void tftSendCommand4(uint8_t command, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t data4) {
  digitalWrite(TFT_CS, LOW); // 
  digitalWrite(TFT_DC, LOW); // Command mode
  SPI.transfer(command);
  digitalWrite(TFT_DC, HIGH); // Command mode
  SPI.transfer(data1);
  SPI.transfer(data2);
  SPI.transfer(data3);
  SPI.transfer(data4);
  digitalWrite(TFT_CS, HIGH);  //
}
// 画面クリア
void cls(bool rot) {
  if (rot) {
    tftSendCommand4(0x2A,0,0,0,131) ; // Colmun Address
    tftSendCommand4(0x2B,0,0,0,161) ; // Row Address
  } else {
    tftSendCommand4(0x2A,0,0,0,160) ; // Colmun Address
    tftSendCommand4(0x2B,0,0,0,131) ; // Row Address
  }
  digitalWrite(TFT_CS, LOW);
  digitalWrite(TFT_DC, LOW); // Command mode
  SPI.transfer(0x2C);
  digitalWrite(TFT_DC, HIGH); // Data mode
  for (int i=0;i<160;i++) {
    for (int j=0;j<131;j++) {
      SPI.transfer(B00000000);
      SPI.transfer(B00000000);
    }
  }
  digitalWrite(TFT_DC, LOW); // Command mode
  digitalWrite(TFT_CS, HIGH);  //
}
// 塗りつぶし
void fill(int xs,int ys , int xe,int ye , uint8_t c1 , uint8_t c2) {
  tftSendCommand4(0x2A,0,xs,0,xe) ; // Colmun Address
  tftSendCommand4(0x2B,0,ys,0,ye) ; // Row Address
  digitalWrite(TFT_CS, LOW);
  digitalWrite(TFT_DC, LOW); // Command mode
  SPI.transfer(0x2C);
  digitalWrite(TFT_DC, HIGH); // Data mode
  for (int i=0;i<xe-xs+1;i++) {
    for (int j=0;j<ye-ys+1;j++) {
      uint8_t dw = c1 ;
      SPI.transfer(dw);
      dw = c2 ;
      SPI.transfer(dw);
    }
  }
  digitalWrite(TFT_DC, LOW); // Command mode
  digitalWrite(TFT_CS, HIGH);  //
}
// BITマップ表示
void drowBitMap(int offsetX , int offsetY , int width, int hight, uint8_t bitMap[]) {
  uint8_t endX = offsetX + width - 1;
  uint8_t endY = offsetY + hight - 1;
  tftSendCommand4(0x2A,0,offsetX,0,endX) ; // Colmun Address
  tftSendCommand4(0x2B,0,offsetY,0,endY) ; // Row Address
  delayMicroseconds(500);
  int pos = 0 ;
  digitalWrite(TFT_CS, LOW);
  digitalWrite(TFT_DC, LOW); // Command mode
  SPI.transfer(0x2C);
  digitalWrite(TFT_DC, HIGH); // Data mode
  for (int row = 0 ; row < hight ; row ++) {
    // 表示データ転送
    // Arduinoだとメモリが足りなくて1画面分を一気に転送する事ができない
    // なので、1Lineずつ送信している
    for (int col = 0 ; col < width * 2 ; col ++ ) {
      SPIBuf[col] = bitMap[pos];
      //      SPIBuf[col] = 0xF8 ;
      pos ++ ;
    }
    SPI.transfer(SPIBuf, width * 2);
  }
  digitalWrite(TFT_DC, LOW); // Command mode
  digitalWrite(TFT_CS, HIGH);  //
}
void DrowFont(uint8_t code , uint8_t x, uint8_t y) {
  int pos = (code - 0x20) * 16 ;
  memset(SPIBuf,0,8*16*2) ;
  for (int i=0;i<16;i++) {
    uint8_t data = ssd1306xled_font8x16[pos + i];
    uint8_t bitMast = 0x01 ; 
    for (int j=0;j<8;j++) {
      int fpos = 0 ;
      if (i<8) {
        fpos = (j*8+i)*2 ;
      } else {
        fpos = ((j+8)*8+(i-8))*2 ;
      }
      if ((data & bitMast) == 0) {
        SPIBuf[fpos] = fontColorB[0] ;
        SPIBuf[fpos+1] = fontColorB[1] ;
      } else {
        SPIBuf[fpos] = fontColorF[0] ;
        SPIBuf[fpos+1] = fontColorF[1] ;
      }
      bitMast <<= 1 ;
    }
  }
  uint8_t endX = x + 7 ;
  uint8_t endY = y + 15;
  tftSendCommand4(0x2A,0,x,0,endX) ; // Colmun Address
  tftSendCommand4(0x2B,0,y,0,endY) ; // Row Address
  digitalWrite(TFT_CS, LOW);
  digitalWrite(TFT_DC, LOW); // Command mode
  SPI.transfer(0x2C);
  digitalWrite(TFT_DC, HIGH); // Data mode
  SPI.transfer(SPIBuf, 8*16*2);
  digitalWrite(TFT_DC, LOW); // Command mode
  digitalWrite(TFT_CS, HIGH);  // 
  delayMicroseconds(500);
}
void DrowStr(char str[] , uint8_t x , uint8_t y) {
  for (int i=0;str[i] != 0 ; i++) {
      DrowFont(str[i],x,y) ;
      x += 8 ;
      if (x+8>=96) {
        x = 0 ;
        y += 16 ;
        if (y + 16 >= 64) {
          y = 0 ; 
        }
      }
  }
}
void setup() {
  Serial.begin(9600);
  Serial.print(F("Pico LCD-1.8 (ST3375)Test"));
  SPI.begin();  //SPIを初期化、SCK、MOSI、SSの各ピンの動作は出力、SCK、MOSIはLOW、SSはHIGH
  SPI.beginTransaction(settings);
  // -----  ST3375 INITIAL -----
  pinMode(TFT_CS, OUTPUT);
  pinMode(TFT_DC, OUTPUT);
  pinMode(TFT_BL, OUTPUT);
  pinMode(TFT_RST, OUTPUT);
  // BACK LIGHT ON
  digitalWrite(TFT_BL, HIGH);
  // --- HARD Ware Reset
  digitalWrite(TFT_RST, HIGH);
  delay(500);                  // VDD goes high at start, pause for 500 ms
  digitalWrite(TFT_RST, LOW);  // Bring reset low
  delay(100);                  // Wait 100 ms
  digitalWrite(TFT_RST, HIGH); // Bring out of reset
  delay(500);                  // Wait 500 ms, more then 120 ms
  // --- SOFT Ware Reset
  tftSendCommand(0x01) ;       // SOFTWARE RESET
  delay(50);
  // --- Initial Comands
  bool r = false ;
  tftSendCommand(0x28) ;            // Display OFF : 0x29 - Display ON
  delay(500);
  tftSendCommand(0x11) ;            // Sleep Out
  delay(500);
  tftSendCommand1(0x3A,05) ;        // 16Bit Pixel Mode
  delay(10);
  tftSendCommand1(0x36,B10100000) ; r = false; // MX MY MV ML RGB MH x x:横向き1
//  tftSendCommand1(0x36,B01100000) ; r = false;  // MX MY MV ML RGB MH x x:横向き2
//  tftSendCommand1(0x36,B00000000) ; r = true;  // MX MY MV ML RGB MH x x:縦向き1
//  tftSendCommand1(0x36,B11000000) ; r = true;  // MX MY MV ML RGB MH x x:縦向き2(多分これがスタンダード)
  tftSendCommand2(0xB6,0x15,0x02) ; // Display settings #5
  tftSendCommand1(0xB4,0x00) ;      // Display inversion control
  tftSendCommand(0x13) ;            // NomalDisplayMode
  tftSendCommand(0x20) ;            // Display Inversion Off
  // ---
  cls(r) ;
  delay(500);
  tftSendCommand(0x29) ;            // Display ON : 0x28 - Display OFF
  delay(500);
}
// the loop function runs over and over again forever
void loop() {
  bool r = false ;
  fontColorB[0] = 0x00 ; fontColorB[1] = 0x00 ; // TEXT BACK GROND COLOR
  fontColorF[0] = 0xFF ; fontColorF[1] = 0xFF ; // TEXT FOR GROND COLOR - WHITE
  for (int i=0;i<4;i++) {
    switch(i) {
      case  0:
        sprintf(str,"B10100000");
        tftSendCommand1(0x36,B10100000) ;// MX MY MV ML RGB MH x x:横向き1
        r = false; 
        break ;
      case  1:
        sprintf(str,"B01100000");
        tftSendCommand1(0x36,B01100000) ; // MX MY MV ML RGB MH x x:横向き2
        r = false; 
        break ;
      case  2:
        sprintf(str,"B00000000");
        tftSendCommand1(0x36,B00000000) ; // MX MY MV ML RGB MH x x:縦向き1
        r = true; 
        break ;
      case  3:
        sprintf(str,"B11000000");
        tftSendCommand1(0x36,B11000000) ; // MX MY MV ML RGB MH x x:縦向き2(多分これがスタンダード)
        r = true; 
        break ;
    }
    cls(r) ;
    DrowStr(str,10,0) ;
    drowBitMap(10,20,96,64,bitmapData2) ;
    fill(10, 90,106, 99,B11111000,B00000000) ;
    fill(10,102,106,111,B00000111,B11100000) ;
    fill(10,113,106,122,B00000000,B00011111) ;
    delay(5000);
 }
}
BITMAPデータの作成
Windows用の画像データをLCD用のBITMAP定義データに変換するツール LCD Image Converter を利用します。
|  | 96x64にリサイズしたImageファイルを読み込みます。 トリミングと拡大は読み込み後にも操作できます。 | 
|  | Optionsを開いて作成するイメージの BlockSizeを8Bitに設定 | 
|  | コンバートを実行 | 
|  | イメージデータの定義ファイルが出来るので スケッチに貼付けて使用できます。 | 
