2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

M5Stack Tab5でRadikoを聞く

2
Posted at

はじめに

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のドキュメントには次の記載があるので、これに関連した事象かもしれません。

image.png

完全に原因を特定したわけではないですが、おまじないで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 と定義されているためで、画面全体に表示されるようにします。

さいごに

全体のソースコードは こちら です。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?