はじめに
M5Stack Tab5でRadikoを聞いてみます。
wakuwaku-koba さんの WebRadio_Japan ライブラリーを使うだけでほとんでできてしまいますが、M5Stack Tab5 用に追加した部分を残します。
M5Stack Tab5 用に追加した部分
WiFi接続
M5Stack Tab5では、ESP32-P4にWiFi機能が内蔵されておらず、ESP32-C6を利用してWiFi接続します。ESP32-P4からESP-C6に接続するためのGPIOを設定する必要があります。
#define SDIO2_CLK GPIO_NUM_12
#define SDIO2_CMD GPIO_NUM_13
#define SDIO2_D0 GPIO_NUM_11
#define SDIO2_D1 GPIO_NUM_10
#define SDIO2_D2 GPIO_NUM_9
#define SDIO2_D3 GPIO_NUM_8
#define SDIO2_RST GPIO_NUM_15
これは setup() で行います。
WiFi.setPins(SDIO2_CLK, SDIO2_CMD, SDIO2_D0, SDIO2_D1, SDIO2_D2, SDIO2_D3, SDIO2_RST);
SmartConfig
オリジナルは、起動時にボタンAを押すとWiFiを設定するためのSmartConfigが開始するようになっていますが、ESP32-P4ではSmartConfigが使用できず、コンパイルエラーになります。
WiFi接続設定は #define で指定して、SmartConfigの箇所はスキップします。
if(M5.BtnA.isPressed()) {
#if !defined(CONFIG_IDF_TARGET_ESP32P4)
// smart config
WiFi.disconnect();
WiFi.mode(WIFI_MODE_APSTA);
WiFi.beginSmartConfig();
M5.Display.println();
M5.Display.print("Waiting for SmartConfig.");
while (!WiFi.smartConfigDone()) {
delay(500);
M5.Display.print(".");
}
M5.Display.println();
M5.Display.print("SmartConfig received.");
while (WiFi.status() != WL_CONNECTED)
delay(100);
WiFi.stopSmartConfig();
WiFi.mode(WIFI_MODE_STA);
#endif
} else {
ヘッドセット
M5Stack Tab5はヘッドセット(イヤホン)が使えます。そのままだと、イヤホンを指してもスピーカーから音が鳴り続けるので、イヤホンを指すとスピーカーから音が出ないように制御します。
ヘッドセット(イヤホン)の状態は、I2Cで接続されたI2C拡張チップのPI4IOで判断し、スピーカーのオン/オフも同様にPI4IOで制御します。
/// Headphone jack detection and speaker amp control
/// PI4IOE5V6408 (E1) at I2C address 0x43
/// Pin 1 = SPK_EN (speaker amplifier power)
/// Pin 7 = HP_DET (headphone jack detect, HIGH when plugged)
/// Register 0x0F = Input Status
/// Register 0x05 = Output State
#define E1_I2C_ADDR 0x43
#define E1_REG_OUTPUT_STATE 0x05
#define E1_REG_INPUT_STATUS 0x0F
#define E1_SPK_EN_BIT 0b00000010 // bit 1
#define E1_HP_DET_BIT 0b10000000 // bit 7
static void checkHeadphone(void)
{
static bool prev_hp_plugged = false;
static bool initialized = false;
// Read Input Status register (0x0F) from E1 (0x43)
uint8_t input_status = M5.In_I2C.readRegister8(E1_I2C_ADDR, E1_REG_INPUT_STATUS, 400000);
bool hp_plugged = (input_status & E1_HP_DET_BIT) != 0;
if (!initialized || hp_plugged != prev_hp_plugged)
{
initialized = true;
prev_hp_plugged = hp_plugged;
if (hp_plugged)
{
// Headphone plugged in -> turn off speaker amp (clear bit 1 of Output State)
M5.In_I2C.bitOff(E1_I2C_ADDR, E1_REG_OUTPUT_STATE, E1_SPK_EN_BIT, 400000);
Serial.println("Headphone plugged: Speaker OFF");
}
else
{
// Headphone unplugged -> turn on speaker amp (set bit 1 of Output State)
M5.In_I2C.bitOn(E1_I2C_ADDR, E1_REG_OUTPUT_STATE, E1_SPK_EN_BIT, 400000);
Serial.println("Headphone unplugged: Speaker ON");
}
}
}
上記の処理を loop() の中で呼び出します。
checkHeadphone();
再起動時の不具合
開発していると時々Tab5がクラッシュして再起動することがありますが、その時に音が出なくなることがありました。
M5Stackのドキュメントには次の記載があるので、これに関連した事象かもしれません。
完全に原因を特定したわけではないですが、おまじないでPI4IOのピンの設定を入れておきます。
/// Explicitly initialize the GPIO expander (PI4IOE5V6408 E1 @ 0x43) for speaker amp
/// This ensures proper state after a crash/warm reboot where the chip may retain
/// stale register values or be in an undefined state.
/// PI4IOE5V6408 registers:
/// 0x01: Device ID / Reset (write bit 0 to soft-reset)
/// 0x03: I/O Direction (0=input, 1=output)
/// 0x05: Output State
/// 0x07: Output High-Impedance (0=push-pull, 1=high-Z)
/// 0x09: Input Default State
/// 0x0B: Pull-up/Pull-down Enable
/// 0x0F: Input Status (read-only)
{
// Set HP_DET (pin 7) as input, disable pull to avoid current drain
// Clear bit 7 of I/O Direction -> input
M5.In_I2C.bitOff(E1_I2C_ADDR, 0x03, E1_HP_DET_BIT, 400000);
// Disable pull-up/down on HP_DET
M5.In_I2C.bitOff(E1_I2C_ADDR, 0x0B, E1_HP_DET_BIT, 400000);
// Set SPK_EN (pin 1) as push-pull output HIGH
// 1. Set output state HIGH first (before enabling output direction)
M5.In_I2C.bitOn(E1_I2C_ADDR, E1_REG_OUTPUT_STATE, E1_SPK_EN_BIT, 400000);
// 2. Set low impedance (push-pull) - clear bit in High-Impedance register
M5.In_I2C.bitOff(E1_I2C_ADDR, 0x07, E1_SPK_EN_BIT, 400000);
// 3. Set as output - set bit in I/O Direction register
M5.In_I2C.bitOn(E1_I2C_ADDR, 0x03, E1_SPK_EN_BIT, 400000);
Serial.println("GPIO expander E1: Speaker amp enabled");
}
画面表示
- Tab5は画面の解像度が高いので、さすがに文字フォントが小さすぎました。フォントサイズを大きくします。
- 全体的には画面表示は正しく行われていますが、黄色のウェーブの表示だけ左の方しか表示されません。これは WAVE_SIZE = 320 と定義されているためで、画面全体に表示されるようにします。
さいごに
全体のソースコードは こちら です。
