以下の内容はhttps://gijin77.blog.jp/archives/2025-06.htmlより取得しました。


◆下記の色々なボードでArduino_GFX_Libraryでパタパタ時計を表示しつつ、RSSニュースを
 無料の「Sound of Text」を使って喋らせてみました。
 以前の記事も参照してみて下さい。
 ・JC3248W535(ESP32S3)で RSSニュース を「[TTS] AquesTalk」を使って喋らせてみた

1.下記のサイズの違うLCDで実現出来ています。
 ①JC1060P470      ESP32P4  7   インチ  1024x600 (jd9165)
 ②JC3248W535     ESP32S3  3.5 インチ   480x320 (AXS15231B)
 ➂LilyGo_Display   ESP32     1.14インチ   240x135 (ST7789)
 ④ESP32P4Devkit    ESP32P4  3.5 インチ   480x320 (ILI9486 RPi用LCD)
 ⑤ESP32P4Devkit    ESP32P4  3.5 インチ   480x320 (ILI9488 LCD)
 ⑥ESP32P4Devkit    ESP32P4  0.96インチ  120x64   (I2C OLED)
 ⑦ESP32_4848S040  ESP32S3   4   インチ    480x480 (st7701) (一部表示乱れあり)

 ①JC1060P470      ESP32P4  7   インチ  1024x600 (jd9165)
 JC1060P470-P1
 
 

 ②JC3248W535     ESP32S3  3.5 インチ   480x320 (AXS15231B)
 JC3248W535-P2
 

 ➂LilyGo_Display   ESP32     1.14インチ   240x135 (ST7789)
 LilyGo_Display-P2


 ④ESP32P4Devkit    ESP32P4  3.5 インチ   480x320 (ILI9486 RPi用LCD)
 esp32p4_RPiLCD_P2
 ◆RPi用3.5インチLCDのドライバは、下記ブログ内記事を参照してみて下さい。
 ・ESP32P4 Devkit GFX_Library_for_Arduino で ILI9486 RPi3.5インチLCD が
  真っ白になるのを解決


 (1)通常は、上記の接続で問題ないのですが、音声出力すると不具合が発生しました。
  対策として、SCKをGPIO0からGPIO6へ変更するアダプタを作成しました。
 RPiアダプタ-1
 RPiアダプタ-2
 RPiアダプタ-4
 esp32p4_devkit_pi_LCD_pin0-6

 
 ⑤ESP32P4Devkit    ESP32P4  3.5 インチ   480x320 (ILI9488 LCD)
 esp32p4_ILI9488-P1
 ◆ILI9488 3.5インチLCDの表示については、下記ブログ内記事を参照してみて下さい。
 ・ESP32 GFX_Library_for_Arduino で ILI9488 3.5'LCD の表示不具合を解決出来た


 ⑥ESP32P4Devkit    ESP32P4  0.96インチ  120x64   (I2C SSD1306 OLED)
 esp32p4_SSD1306-P1
 ◆I2C接続SSD1306表示については、下記ブログ内記事を参照してみて下さい。
 ・ESP32 でI2C接続 SSD1306 GFX_Library_for_Arduino インターフェイスで
  表示出来るようにしてみた



 ⑦ESP32_4848S040  ESP32S3   4   インチ    480x480 (st7701) (一部表示乱れあり)
 ESP32_4848S040-P1
 ◆ESP32_4848S040のI2Sの配線については、下記ブログ内記事を参照して下さい。
 ・4.0inch ESP32-4848S040 で音が出ない 解析と改修
 


2.今回は、音声合成を無料のクラウドサービス「Sound of Text」を使いました。
 ①試しに下記サイトでテキストを入力し、デモ音声を聞くことが出来ます。
  https://soundoftext.com/

 ②サイトにアクセスしたら日本語を選択し、適当な日本語文章をテキストBOXに入力し、
  送信をクリックします。
 sot_demo-1

 ➂下にスクロールして、「PLAY」をクリックすると、音声が流れます。
 sot_demo-2
 
 ④「DOWNLOAD」をクリックすると保存フォルダを選択し、「xxx.MP3」ファイルが
  保存されます。後で聞くことが出来ます。
 sot_demo-3

 ⑤APIも公開されています。
  APIドキュメント

3.スケッチについて
 ①(保障無しの自己責任で)  Fclock_News_SOT_V3.zip

 ②Fclock_News_SOT_V3.zipの中身
 SOT_V3

 ➂ボードの選択は、「Sound_of_Text.h」の中で例:「#define JC1060P470 」の様に
  選択して、コンパイル&書き込みします。

//Sound_of_Text.h
//2025/06/28 By JK1VCK パタパタ時計、News、音声合成
//blog URL:https://gijin77.blog.jp/archives/44980183.html

#ifndef _SOUND_OF_TEXT_H_
#define _SOUND_OF_TEXT_H_
#include <Arduino.h> 
#include <stdint.h>

//#define    LilyGo_Display  // esp32 LilyGo T-Display Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS)
//#define    JC3248W535      // esp32s3 Dev USBCDCOnBoot=en Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=OPIPSRAM
//#define    ESP32_4848S040  // esp32s3 Dev USBCDCOnBoot=ds Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=OPIPSRAM 
#define  JC1060P470        // esp32p4 Dev USBCDCOnBoot=en Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=en
//#define  ESP32P4Devkit     // esp32p4 Dev USBCDCOnBoot=en Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=en USB_Mode=Hard

//ESP32P4DevkitのLCDの選択は、下記で
//#define P4_SSD1306   //128x64
//#define P4_RPi35LCD  //480x320

//プロトタイプ宣言
void i2s_setup();
void TTS_task(void* pv);
void speak_text(String text);
void initTTS();
int TTS_isPlay();

#endif // !defined(_SOUND_OF_TEXT_H_)


以上

ブログトップへ

◆ESP32 GFX_Library_for_Arduinoライブラリを使って通常の「Arduino_ILI9488」では、
 表示出来ませんでした。
 初期化コマンドを弄ったりSPI指定を替えたりしましたが、表示しませんでした。
 色々ネットで検索していたら、「Arduino_ILI9488_18bit」を使えば良い事が分かりました。

1.スケッチの一部

 Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK,
   TFT_MOSI, TFT_MISO);
 //Arduino_GFX *gfx = new Arduino_ILI9488(bus, TFT_RST, 0); // NG
 Arduino_GFX *gfx = new Arduino_ILI9488_18bit(bus, TFT_RST, 0); // <-これで表示OK

2.テスト用スケッチ(ILI9488_Test.ino)
//ILI9488_Test.ino
//V2025/06/28 By JK1VCK ILI9888 3.5'LCD
//blog URL:https://gijin77.blog.jp/archives/45000692.html

#include <Arduino_GFX_Library.h>

#define TFT_DC    17
#define TFT_RST   16
#define TFT_CS    5
#define TFT_MOSI  23
#define TFT_SCK   18
#define TFT_MISO  19

Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
//Arduino_GFX *gfx = new Arduino_ILI9488(bus, TFT_RST, 0); // 3.5 LCD
Arduino_GFX *gfx = new Arduino_ILI9488_18bit(bus, TFT_RST, 0); // 3.5 LCD

uint16_t color[8] ={BLACK,BLUE,GREEN,CYAN,RED,MAGENTA,YELLOW,WHITE};
int32_t w, h, n, n1, cx, cy, cx1, cy1, cn, cn1;
void setup() {
  Serial.begin(115200);
  Serial.println("LCD init success");
  gfx->begin();
}
void get_whxy(){
  w = gfx->width();
  h = gfx->height();
  cx = w / 2;
  cy = h / 2;
}
void loop() {
  int wt=500;
  char msg[200];
  Serial.println("LCD Test Start");
  for(int r=0;r<8;r++){
    gfx->setRotation(r);get_whxy();
    sprintf(msg," R=%d W=%d H=%d",r,w,h);
    Serial.println(msg);
    gfx->fillScreen(BLACK);gfx->setCursor(0,0);gfx->setTextColor(ORANGE);
    gfx->setTextSize(3); 
    //if (w==480) gfx->setTextSize(2); else gfx->setTextSize(1);
    gfx->print(msg);
    for (int c=0;c<8;c++) {
      gfx->setCursor(0, cy-1+c*(cy/8));
      gfx->setTextSize(3);
      gfx->setTextColor(color[c]);
      if (w==480) gfx->print("Hello LCD Test 123 ABC abc");
      else        gfx->print("Hello LCD Test V7");
      gfx->fillRect(c*(w/8),(cy/8)+2,(w/8),cy-(cy/8),color[7-c]);
      delay(wt);
    }
    delay(5000);
  }
  Serial.println("LCD Test end");
}


3.表示画面
 ①Arduino_ILI9488_18bitでOK
 ILI9488_18bit
 
 ②Arduino_ILI9488でNG
 ILI9488

以上



ブログトップへ

◆ESP32P4 Devkitは、dsi接続の7インチ,10.1インチの標準のLCD付が販売されていますが、
 ちょっと高価です。
 このボードにはraspiと同様な拡張コネクタが付いていましたので、安価なraspi用3.5インチ
 LCDが使えないかと思い、ボードだけ購入してみました。
 このボードについて詳しくは、下記で
 ESP32-P4-Module-DEV-KIT

 *youtube動画(字幕で日本語を表示出来ます)
 ESP32-P4-Module vs. Raspberry Pi 4 & Raspberry Pi 5. Can it beat Raspberry Pi?

 RPiLCD-1

 RPiLCD_P4

 esp32p4_devkit_pi_LCD_pin

1.raspi用3.5インチLCDについて
 ①ハード的には、そのままコネクタに差し込めます。
 ②LCDのライブラリは、他のボードで、色々使っている関係上「 GFX_Library_for_Arduino」
  を使いたい。
 ➂ドライバICは、「ILI9486」らしい。
 ④接続形態は、SPIらしい。
 ⑤上記を元に「 GFX_Library_for_Arduino」を使い、テスト用スケッチを作りました。
  *コンパイラ、書き込みも出来ましたが、画面が真っ白のままでした。
 
2.動かすまでの奮闘
 ①「ILI9486」データシートからの初期化コマンドを色々と試してみましたが、
  真っ白のままで変化なし

 ②ネットで調べましたがESP32P4での動作報告は、検索できませんでした。
  よって、「ESP32」で試験を開始しました。
  
3.「ESP32 Devkit」での奮闘
 ①ブレッドボートに簡単に抜き差し出来るようアダプタを作成しました。
  (「ILI9341」「ILI9488」等も試験出来るように)
 RPiアダプタ

 ②ESP32でも相変わらず真っ白のままです。

 ➂ライブラリを替えて試験すると、正常に表示しましたので、ハードの接続は
  問題ない事が、分かりました。

 ④動作するライブラリの初期化コードを使っても、真っ白のままてす。

 ⑤SPIスピードを替えても駄目です。一週間以上悩みました。

 ⑥色々、調べていて、やっと分かりました。
  *「raspi用3.5LCDデバイスは実際にはSPIではありませんでした。
  *これは並列インターフェースに接続された16ビットのシフトレジスタで、
   20MHzで動作可能」
  *よって常に16ビット送るようにダミーを入れなくてはならなかったみたいです。
  *これで、初期コマンドが、認識されて画面表示が変わりました。

  void Arduino_RPiILI9486Bus::writeCommand(uint8_t c) {
  //Serial.printf("\nCommand=%02X ",c);
    digitalWrite(_dc, LOW);
    _spi->transfer(0); //<--ここにダミーを送って16bitにする必要が有る
    _spi->transfer(c);    //コマンド送信(8bit)
  }

  void Arduino_RPiILI9486Bus::write(uint8_t d) {
  //Serial.printf("Data=%02X ",d);
    digitalWrite(_dc, HIGH);
    _spi->transfer(0); //<--ここにダミーを送って16bitにする必要が有る
    _spi->transfer(d); // データ送信(8bit)
  }

 ◆raspi用3.5LCD 参考回路図

4.原因が、判明しましたので「GFX_Library_for_Arduino」へ組み込みます。
  (保障無しの自己責任で)
 ①「src」フォルダに「custom」フォルダを作り、そこへ「Arduino_RPiILI9486Bus.h」を
   保存します。
 ②同じく「Arduino_RPiILI9486Bus.cpp」を保存します。
 
 *「Arduino_RPiILI9486Bus.h」の内容
//Arduino_RPiILI9486Bus.h
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#pragma once

#include <Arduino.h>
#include <SPI.h>
#include "../Arduino_DataBus.h"

class Arduino_RPiILI9486Bus : public Arduino_DataBus {
public:
  Arduino_RPiILI9486Bus(SPIClass *spi, int8_t dc, int8_t cs, int8_t sck, int8_t mosi, int8_t miso);

  // 必須のオーバーライド関数(仮想関数)
  bool begin(int32_t speed = SPI_DEFAULT_FREQ, int8_t dataMode = GFX_NOT_DEFINED) override;
  void end();

  void beginWrite() override;
  void endWrite() override;

  void writeCommand(uint8_t c) override;
  void writeCommand8b(uint8_t c);
  void writeCommand16(uint16_t c) override;
  void writeCommandBytes(uint8_t *data, uint32_t len) override;

  void write(uint8_t d) override;
  void write16(uint16_t d) override;
  void writeData(uint8_t d);
  void writeData16(uint16_t d);
  void writeBytes(uint8_t *data, uint32_t len) override;

  void writeRepeat(uint16_t p, uint32_t len) override;
  void writePixels(uint16_t *data, uint32_t len) override;

private:
  SPIClass *_spi;
  uint32_t _spi_speed;
  int8_t _dc, _cs, _sck, _mosi, _miso;
  int32_t _speed;
};



 
 *「Arduino_RPiILI9486Bus.cpp」の内容
//Arduino_RPiILI9486Bus.cpp
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#include "Arduino_RPiILI9486Bus.h"

Arduino_RPiILI9486Bus::Arduino_RPiILI9486Bus(SPIClass *spi, int8_t dc, int8_t cs, int8_t sck, int8_t mosi, int8_t miso)
  : _spi(spi), _dc(dc), _cs(cs), _sck(sck), _mosi(mosi) 
{
  _spi = spi;
  _dc = dc;
  _cs = cs;
  _sck = sck;
  _mosi = mosi;
  _miso = miso;
  _spi_speed = 20000000;  // 20MHz を仮設定
}

bool Arduino_RPiILI9486Bus::begin(int32_t speed, int8_t dataMode) {
 if (speed == -1) {
    speed = _spi_speed;  // 初期値を使用
  } else {
    _spi_speed = speed;  // 明示指定されたら上書き
  }
  pinMode(_dc, OUTPUT);
  pinMode(_cs, OUTPUT);

  if (_sck != -1 && _mosi != -1) {
    _spi->begin(_sck, -1, _mosi);
  } else {
    _spi->begin();
  }

  digitalWrite(_cs, HIGH);
  digitalWrite(_dc, HIGH);
  _spi->begin(_sck, _miso, _mosi,_cs);
  _spi->beginTransaction(SPISettings(speed, MSBFIRST, dataMode));
  
  Serial.printf("begin: spi_speed=%ld cs=%d dc=%d sck=%d mosi=%d miso=%d \n",speed,_cs,_dc,_sck,_mosi,_miso);
  return true;
}

void Arduino_RPiILI9486Bus::end() {
  _spi->end();
}

void Arduino_RPiILI9486Bus::beginWrite() {
  //Serial.println("beginWrite");
  digitalWrite(_cs, LOW); // TODO: SPIトランザクション開始処理
}

void Arduino_RPiILI9486Bus::endWrite() {
//Serial.println("\nendWrite");
  digitalWrite(_cs, HIGH); // TODO: SPIトランザクション終了処理
}

void Arduino_RPiILI9486Bus::writeCommand(uint8_t c) {
//Serial.printf("\nCommand=%02X ",c);
  digitalWrite(_dc, LOW);
  _spi->transfer(0);
  _spi->transfer(c);
}

void Arduino_RPiILI9486Bus::writeCommand8b(uint8_t c) {
//Serial.printf("\nCommand=%02X ",c);
  digitalWrite(_dc, LOW);
  _spi->transfer(c);
}

void Arduino_RPiILI9486Bus::writeCommand16(uint16_t cmd) {
//Serial.println("writeCommand16");
    writeCommand8b((uint8_t)(cmd >> 8));
    writeCommand8b((uint8_t)cmd);    // TODO: 16bitコマンド送信処理
}

void Arduino_RPiILI9486Bus::writeCommandBytes(uint8_t *data, uint32_t length) {
//Serial.println("writeCommandByte");
  digitalWrite(_dc, LOW);
  while (length--)  {
    writeCommand8b(*data++);  // TODO: 任意の長さのコマンド送信処理
  }
}

void Arduino_RPiILI9486Bus::write(uint8_t d) {
//Serial.printf("Data=%02X ",d);
  digitalWrite(_dc, HIGH);
  _spi->transfer(0);
  _spi->transfer(d); // TODO: データ送信(8bit)
}

void Arduino_RPiILI9486Bus::writeData(uint8_t d) {
//Serial.printf("Data=%02X ",d);
  digitalWrite(_dc, HIGH);
  _spi->transfer(d); // TODO: データ送信(8bit)
}

void Arduino_RPiILI9486Bus::write16(uint16_t data) {
//Serial.println("write16");
  writeData((uint8_t)(data >> 8));
  writeData((uint8_t)data);      // TODO: データ送信(16bit)
}

void Arduino_RPiILI9486Bus::writeBytes(uint8_t *data, uint32_t length) {
  digitalWrite(_dc, HIGH); // データモード
  while (length--) {
    writeData(*data++);
  }
}

void Arduino_RPiILI9486Bus::writeRepeat(uint16_t p, uint32_t len) {
//Serial.printf("writeRepeat data=%04X len=%ld \n",p,len);
  digitalWrite(_dc, HIGH); // データモード
  for (uint32_t i = 0; i < len; ++i) {
  _spi->transfer((uint8_t)(p >> 8)); // TODO: データ送信(8bit)
  _spi->transfer((uint8_t)p);        // TODO: データ送信(8bit
  }
}

void Arduino_RPiILI9486Bus::writePixels(uint16_t *data, uint32_t len) {
  //Serial.println("writePixels");
  digitalWrite(_dc, HIGH);
  for (uint32_t i = 0; i < len; ++i) {
    _spi->transfer((uint8_t)(data[i] >> 8)); // TODO: データ送信(8bit)
    _spi->transfer((uint8_t)data[i]);        // TODO: データ送信(8bit
  }
}

 
 ➂試験用「RPiLCD_Test.ino」の内容
//RPiLCD_Test.ino
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#include <Arduino_GFX_Library.h>

#define  ESP32Devkit
//#define  ESP32P4Devkit       // esp32p4 DEV M Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=en USBCDCOnBoot=en USB_Mode=Hard

#if defined(ESP32P4Devkit)
#include "custom/Arduino_RPiSWSPI_P4.h"
//ESP32P4
#define TFT_CS    36
#define TFT_DC     4
#define TFT_RST    1
#define TFT_SCK    0
#define TFT_MOSI   3
#define TFT_MISO  -1
Arduino_DataBus *bus = new Arduino_RPiSWSPI_P4(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Arduino_GFX *gfx = new Arduino_ILI9486(bus, TFT_RST, 0); //RPi 3.5 LCD

#elif defined(ESP32Devkit)
#include "custom\Arduino_RPiILI9486Bus.h"
//ESP32
#define TFT_DC    17
#define TFT_RST   16
#define TFT_CS    5
#define TFT_MOSI  23
#define TFT_SCK   18
#define TFT_MISO  19
//Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
//Arduino_DataBus *bus = new Arduino_SWSPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Arduino_DataBus *bus = new Arduino_RPiILI9486Bus(&SPI, TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Arduino_GFX *gfx = new Arduino_ILI9486(bus, TFT_RST, 0); //RPi 3.5 LCD
#endif

uint16_t color[8] ={BLACK,BLUE,GREEN,CYAN,RED,MAGENTA,YELLOW,WHITE};
int32_t w, h, n, n1, cx, cy, cx1, cy1, cn, cn1;
void setup() {
  Serial.begin(115200);
  Serial.println("LCD init success");
  gfx->begin();
}
void get_whxy(){
  w = gfx->width();
  h = gfx->height();
  cx = w / 2;
  cy = h / 2;
}
void loop() {
  int wt=500;
  char msg[200];
  Serial.println("LCD Test Start");
  for(int r=0;r<8;r++){
    gfx->setRotation(r);get_whxy();
    sprintf(msg," R=%d W=%d H=%d",r,w,h);
    Serial.println(msg);
    gfx->fillScreen(BLACK);gfx->setCursor(0,0);gfx->setTextColor(ORANGE);
    gfx->setTextSize(3); 
    //if (w==480) gfx->setTextSize(2); else gfx->setTextSize(1);
    gfx->print(msg);
    for (int c=0;c<8;c++) {
      gfx->setCursor(0, cy-1+c*(cy/8));
      gfx->setTextSize(3);
      gfx->setTextColor(color[c]);
      if (w==480) gfx->print("Hello LCD Test 123 ABC abc");
      else        gfx->print("Hello LCD Test V7");
      gfx->fillRect(c*(w/8),(cy/8)+2,(w/8),cy-(cy/8),color[7-c]);
      delay(wt);
    }
    delay(5000);
  }
  Serial.println("LCD Test end");
}


 ④表示試験画面(ローテンション1)
 RPiLCD_esp32-1
 ⑤表示試験画面(ローテンション2)
 RPiLCD_esp32-2

5.続いて本題の「ESP32P4 Devkit」での表示
  (保障無しの自己責任で)
 ①「ESP32P4」ではSPIが使えず、「ESP32」のままでは表示しませんでした。
 ②よって、SPIインターフェースをGPIOのビット操作で実現しました。
 ➂先ほど作った「src」->「custom」フォルダへ「Arduino_RPiSWSPI_P4.h」を保存します。
 ④同じく「Arduino_RPiSWSPI_P4.cpp」を保存します。
 
 *「Arduino_RPiSWSPI_P4.h」の内容
 
//Arduino_RPiSWSPI_P4.h
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#ifndef _ARDUINO_RPISWSPI_P4_H_
#define _ARDUINO_RPISWSPI_P4_H_

#include "../Arduino_DataBus.h"

typedef volatile uint32_t *PORTreg_t;

class Arduino_RPiSWSPI_P4 : public Arduino_DataBus
{
public:
  Arduino_RPiSWSPI_P4(int8_t dc, int8_t cs, int8_t _sck, int8_t _mosi, int8_t _miso = GFX_NOT_DEFINED); // Constructor

  bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
  void beginWrite() override;
  void endWrite() override;
  void writeCommand(uint8_t) override;
  void writeCommand16(uint16_t) override;
  void writeCommandBytes(uint8_t *data, uint32_t len) override;
  void write(uint8_t) override;
  void write16(uint16_t) override;
  void writeRepeat(uint16_t p, uint32_t len) override;
  void writePixels(uint16_t *data, uint32_t len) override;
  void writeBytes(uint8_t *data, uint32_t len) override;
  uint8_t read();
  void readBytes(uint8_t *data, uint32_t len);
   
private:
  void writedata(uint8_t d);
  int8_t _dc, _cs;
  int8_t _sck, _mosi, _miso;

};
#endif // _ARDUINO_RPISWSPI_P4_H_

 
 *「Arduino_RPiSWSPI_P4.cpp」の内容

//Arduino_RPiSWSPI_P4.cpp
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#include "Arduino_RPiSWSPI_P4.h"

#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32P4)

#include "soc/gpio_struct.h"
#include "hal/gpio_ll.h"  // GPIO操作の低レベルヘッダ(ESP-IDF)


Arduino_RPiSWSPI_P4::Arduino_RPiSWSPI_P4(int8_t dc, int8_t cs, int8_t sck, int8_t mosi, int8_t miso)
    : _dc(dc), _cs(cs), _sck(sck), _mosi(mosi), _miso(miso)
{
}

inline void GPIO_HIGH(uint8_t pin) { //ピン番号は0-31まで
  GPIO.out_w1ts.val = (1UL << pin);
}

inline void GPIO_LOW(uint8_t pin) { //ピン番号は0-31まで
  GPIO.out_w1tc.val = (1UL << pin);
}

bool Arduino_RPiSWSPI_P4::begin(int32_t, int8_t) {
  pinMode(_dc, OUTPUT);
  digitalWrite(_dc, HIGH);

  pinMode(_cs, OUTPUT);
  digitalWrite(_cs, HIGH);

  pinMode(_sck, OUTPUT);
  digitalWrite(_sck, LOW);

  pinMode(_mosi, OUTPUT);
  digitalWrite(_mosi, LOW);

  if (_miso != GFX_NOT_DEFINED) {
    pinMode(_miso, INPUT);
  }
  Serial.printf("begin: cs=%d dc=%d sck=%d mosi=%d miso=%d \n",_cs,_dc,_sck,_mosi,_miso);
  return true;
}
void Arduino_RPiSWSPI_P4::beginWrite() {
  digitalWrite(_dc, HIGH); // Data mode
  digitalWrite(_cs, LOW);
}

void Arduino_RPiSWSPI_P4::endWrite() {
  digitalWrite(_cs, HIGH);
}

void Arduino_RPiSWSPI_P4::writedata(uint8_t d) {
  for (uint8_t bit = 0x80; bit; bit >>= 1) {
    if (d & bit) {
      GPIO.out_w1ts.val = (1UL << _mosi);  // Set
    } else {
      GPIO.out_w1tc.val = (1UL << _mosi);  // Clear
    }
    GPIO.out_w1ts.val = (1UL << _sck);     // SCK HIGH
    GPIO.out_w1tc.val = (1UL << _sck);     // SCK LOW
  }
}

void Arduino_RPiSWSPI_P4::writeCommand(uint8_t c) {
//  Serial.printf("\ncmd=%02X ", c);
  GPIO_LOW(_dc);
  writedata(0);  // Dummy write?
  writedata(c);
  GPIO_HIGH(_dc);
}

void Arduino_RPiSWSPI_P4::writeCommand16(uint16_t p) {
  uint8_t hi = p >> 8, lo = p & 0xFF;
  writedata(hi);
  writedata(lo);
}

void Arduino_RPiSWSPI_P4:: writeCommandBytes(uint8_t *data, uint32_t len) {
  while (len--) {
    uint16_t c = *data++;
    writedata(c >> 8);
    writedata(c & 0xFF);
  }	
}

void Arduino_RPiSWSPI_P4::write(uint8_t d) {
//Serial.printf("data=%02X ",d);
  writedata(0);
  writedata(d);
}

void Arduino_RPiSWSPI_P4::write16(uint16_t p) {
  uint8_t hi = p >> 8, lo = p & 0xFF;
  writedata(hi);
  writedata(lo);
}

void Arduino_RPiSWSPI_P4::writeRepeat(uint16_t p, uint32_t len) {
  uint8_t hi = p >> 8, lo = p & 0xFF;
  while (len--) {
    writedata(hi);
    writedata(lo);
  }
}

void Arduino_RPiSWSPI_P4::writePixels(uint16_t *data, uint32_t len)
{
  while (len--) {
    uint16_t c = *data++;
    writedata(c >> 8);
    writedata(c & 0xFF);
  }
}

void Arduino_RPiSWSPI_P4::writeBytes(uint8_t *data, uint32_t len)
{
  while (len--) {
    writedata(*data++);
  }
}

uint8_t Arduino_RPiSWSPI_P4::read()
{
  uint8_t r = 0;
  for (uint8_t i = 0x80; i; i >>= 1) {
    GPIO.out_w1ts.val = (1UL << _sck);     // SCK HIGH
    if (digitalRead(_miso)) r |= i;
    GPIO.out_w1tc.val = (1UL << _sck);     // SCK LOW
  }
  return r;
}

void Arduino_RPiSWSPI_P4::readBytes(uint8_t *data, uint32_t len)
{
  while (len--) {
    *data++ = read();
  }
}

#endif



 
 ⑤試験用スケッチは、先ほどの物で最初の#defineで「ESP32P4_Devkit」を有効にします。
  //#define  ESP32Devkit
  #define  ESP32P4Devkit

 ⑥表示試験画面(ローテンション1)
 RPiLCD_esp32p4-4

 ⑦表示試験画面(ローテンション2)
 RPiLCD_esp32p4-3

これで「raspi用3.5インチLCD」が「GFX_Library_for_Arduino」で使えるようになりました。

以上


ブログトップへ

◆4.0inch_ESP32-4848S040を入手して色々弄って遊んでいました。
 ところがI2S経由で音出しをした所、音が出ませんでした。

1.新品なのにちょっと躊躇しましたが、裏ブタを外してみました。
 ESP32_4848S040-1

 ①スピーカ端子付近の部品配置を、分析して見ましたら、GPIOがI2Sアンプへの
  接続用「0Ω」チップ抵抗が付いていませんでした。
  これでは、音が出ないのは、当然です。
  チップ抵抗の持ち合わせが無かったのでジャンパー線で繋ぎました。
  老眼では、大変難儀しました。

 I2S_NG

 ②このボードGPIOのほとんどを4インチ480x480のLCDに使っています。
  標準では拡張用の外部端子は、出ていません。
  回路図を眺めると、未使用のGPIO35,36,37が有りました。
  裏ブラを開けたついでに、このGPIOを外部に出す改修もしました。
 ◆2025/10/05追記
  GPIO35,36,37は、内部フラッシュメモリ、PSRAMで使われている可能性が有り
  外部で使うと動作が不安定になる事があるため、使わない方が良さそうです。


 I2S_OK

 GPIO拡張
  
 ➂音出しのテストプログラムを走らせ、無事音が出ました。めでたしめでたし。  
  後、外部に出したGPIO35,36,37にLEDを接続して点灯する事を確認しました。

 

 ④テストスケッチ
//i2s_test.ino
//V2025/06/20 by JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44904481.html

#include "driver/i2s.h"
#include <math.h>

#define I2S_NUM         I2S_NUM_0
#define SAMPLE_RATE     44100
#define TONE_FREQ_HZ    1000
#define DURATION_SEC    5
#define VOLUME          10000

#define I2S_BCK_IO      1   // BCK
#define I2S_WS_IO       2   // LRCK / WS
#define I2S_DO_IO       40  // DOUT

void setupI2S() {
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = I2S_COMM_FORMAT_STAND_MSB,
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = 64,
    .use_apll = false,
    .tx_desc_auto_clear = true
  };

  i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_BCK_IO,
    .ws_io_num = I2S_WS_IO,
    .data_out_num = I2S_DO_IO,
    .data_in_num = I2S_PIN_NO_CHANGE
  };

  i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM, &pin_config);
  i2s_zero_dma_buffer(I2S_NUM);
}

void playTone() {
  const int samples = SAMPLE_RATE * DURATION_SEC;
  const int bytes_per_sample = 4;  // 16bit * 2ch
  int16_t sampleBuffer[256];

  for (int i = 0; i < samples; i += 128) {
    for (int j = 0; j < 128; j++) {
      float t = (float)(i + j) / SAMPLE_RATE;
      int16_t val = (int16_t)(VOLUME * sinf(2 * PI * TONE_FREQ_HZ * t));
      sampleBuffer[2 * j + 0] = val;  // Left
      sampleBuffer[2 * j + 1] = val;  // Right
    }
    size_t bytes_written;
    i2s_write(I2S_NUM, sampleBuffer, sizeof(sampleBuffer), &bytes_written, portMAX_DELAY);
  }
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  pinMode(35, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(37, OUTPUT);
  Serial.println("I2S 初期化中...");
  setupI2S();
  Serial.println("1kHz サイン波を出力します");
  playTone();
  Serial.println("終了しました");

}
int w=1000;
void loop() {
  digitalWrite(35, HIGH);delay(w);
  digitalWrite(35, LOW);delay(w);
  digitalWrite(36, HIGH);delay(w);
  digitalWrite(36, LOW);delay(w);
  digitalWrite(37, HIGH);delay(w);
  digitalWrite(37, LOW);delay(w);  
}


2.もう一つ、このボードには、RST,BOOTの釦は付いているのですが裏蓋を
  付けると、アクセス出来ません。これでは使いたい時に使えないので
  裏ブタにアプローチ用の穴を開けました。
 ESP32_4848S040-2

3.参考回路図(販売店サイトより)
 ESP32-4848S040回路図1

 ESP32-4848S040回路図2

以上 色々遊べそうです。


ブログトップへ

◆以前からTAB5で「Xiaozhi」を動かそうと思い色々調べていましたら、
 本日、VSCode(ESP-IDF)環境で「xiaozhi-esp32-v174」をTAB5用に
 コンパイルが出来て書き込むことが出来ました。
 先人の方に、感謝です。

 tab5_小智_2

1.構築方法
 ①下記サイトからソース一式をダウンロードします。
  6/5の時点では、エラーで実行できませんでしたが、本日ダウンロード
  したバージョンは、見事に動作しました。素晴らしい!
  xiaozhi-esp32

 ②コンパイルするにあたって、ESP-IDFの環境を構築して下さい。
 *私は、Visial Studio Codeをインストールしました。
  でも、初めてでGUI環境ではまだビルド出来ていません。
  今回は、パワーシェル内でビルドしました。
 VSCODE

 ➂次は、解凍して、"xiaozhi-esp32-main\main\boards\m5stack-tab5"フォルダ内
  の「sdkconfig.tab5」を「xiaozhi-esp32-main」フォルダ内に「sdkconfig」として
  コピーします。

 ④idf.py set-target esp32p4    *ターゲットをESP32P4へ設定
 
 ⑤idf.py build           *ビルド
 
 ⑥idf.py -p COM10 flash monitor *書き込み&モニター
 
 以上でコンパイル&書き込みできました。
 

2.再起動させて、後はWiFiの設定等実施します。
 この辺については、下記ブログ内記事を参照して下さい。
 ・小智「XiaoZhi」を ATOMS3/ESP32S3 にて 日本語 で話してみた
 
 ①今回デバイスの登録時に下記の画面が出て来ました。
  その内、商用化されるのでしょうか。

 tab5_登録画面

 ②無事登録出来て、デバイスのバージョンが、!.7.4となっていて日々アップデートが
  進んでいるようです。
 tab5_v174
3.実際の様子

 


以上
 

ブログトップへ



以上の内容はhttps://gijin77.blog.jp/archives/2025-06.htmlより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14