[M5Stack]オーディオ再生時にGPIO26を使えるようにする方法

M5StackでMP3などのオーディオファイルを再生する場合、ESP8266Audioというライブラリがよく使われます。

オーディオファイルを再生すると、I2Sインターフェースにデジタルのオーディオデータが出力されますが、そのままでは音にならないので、DACを介してアナログ電圧に変換します。M5Stackに内蔵のESP32はDACを持っていますので、そのDACを使うのが手っ取り早い選択になります。

このDACを使うと、左右の音声のアナログ電圧がGPIO25及びGPIO26ピンに出力されます。M5Stackのスピーカーは1個で、GPIO25ピンからの音声が出力されるようになっています。
ステレオで再生したい場合はGPIO26ピンにアンプとスピーカを接続する必要があります。

M5Stackに他のモジュールをスタックし、色々な機能を持たせたいと思った時、GPIOのピンが不足する事があります。
オーディオを再生しながらGPIO26ピンが使えると有難いですが問題が生じます。

次の波形は、GPS受信機からのUARTのシリアルデータがGPIO26に入力されている時の波形で、左側は正常な場合、右側はオーディオ再生した場合の波形です。
右側の波形でLowの時の電圧が0Vでなく1.2V程度に上昇しています。
これはDACからの出力とGPS受信機からの出力が競合しているためです。

この問題を解決するためにはGPIO26を通じてのDACの出力を止める必要があります。

色々調べたところ、次のようにするとうまく行く事が分かりました。

修正するファイル:
C:\Users\ユーザ\Documents\Arduino\libraries\ESP8266Audio\src\AudioOutputI2S.cpp

bool AudioOutputI2S::begin(bool txDAC)
{
..
    if (output_mode == INTERNAL_DAC || output_mode == INTERNAL_PDM)
    {
      if (this->mono)                               // <<<< 追加
      {                                             //
        i2s_pin_config_t pinMono;                   //
        memset(&pinMono,0,sizeof(pinMono));         //
        pinMono.data_out_num = 25;                  //
        i2s_set_pin((i2s_port_t)portNo, &pinMono);  //
        i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN); //
      }                                             // <<< 追加
     else
      {
        i2s_set_pin((i2s_port_t)portNo, NULL);      // <<< 元からあったコード
        i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);  // <<<
      }
  }
..
}

上記の修正を行った後、次のようなコードでオーディオ再生を行います。

void playWaveFile()
{
    file_w = new AudioFileSourceSD("/sample.wav");
    out_w = new AudioOutputI2S(0,1); 
    out_w->SetOutputModeMono(true);   // <<< この設定を必ず行う
    out_w->SetGain(0.3); 
    wav = new AudioGeneratorWAV(); 

    wav->begin(file_w, out_w);
    while(wav->isRunning()){
     if (!wav->loop()) wav->stop();
    }
}

これでGPIO26が自由に使えるようになりました。