マイコン工作実験日記

Microcontroller を用いての工作、実験記録

A2DP sink機能の追加

2024-06-25 20:02:32 | DoomPlayer

Nucleo-U575ZIのDoomPlayerは、随分前にフラッシュの使用量が1MBを超え、内蔵SRAMの使用量もすでに90%を超えているのですが、なんとかA2DP sink機能を追加したいと思い作業中です。この機能によりスマホで再生した楽曲ファイルやストリームをDoomPlayerで再生することができます。基本的にBTStackのa2dp_sink_demoを使用しているのですが、昨年試したAVRCP Cover Art 機能は盛り込まない方向です。理由はSTM32U575にはハードウェアでのJPEGデコード機能が無いのと、SRAMの容量やMCUの処理速度的にもキツそうなため。

A2DP sinkとして動かす場合には、上の写真に示したようにSDカードを抜いた状態で起動することで、動作モードを切り替えることとしました。

楽曲のタイトルやアーティスト名を普通に表示しているぶんには問題ないのですが、この文字列が長くなり水平スクロールしながら表示する必要が生じた場合に、表示処理の負荷が高くなりスペクトラム効果表示の更新が遅くなったり、タッチパネル操作の反応が悪くなったりという現象が発生してしまいます。使用するフォントとサイズを小さくすることで少しは改善できたのですが、それにも限りが。。。


チート・コード

2024-06-06 12:33:24 | DoomPlayer

DOOMにはチートコード(Cheat Codes)という機能があります。キーボードからidで始まるおまじない文字列を入力することで、体力を回復したりするズルが行える機能です。DoomPlayerでは、キーボードをつなげなくても上記の画像に示したようにLCDのタッチパネルに表示されたメニューや仮想キーボードから入力することが可能です。

この表示は、DOOMの画面表示の上にlvglで作成したGUI画面を重ね合わせて表示することで実現されています。STM32H7B3I-DKのようLTDCをサポートするデバイスであり十分なDRAMを搭載するボードの場合には、それぞれの画面を独立した2つのレイヤに割り当て、それらをLTDCの機能で重ね合わせ表示することで実現することができました。しかしながら、Nucleo-U575ZI-QのようにLTDCをサーボーとしておらず、メモリ容量にも制約がある環境では実現方法を考えなければなりません。今回は、次のような手段で重ね合わせ表示を実現しています。

  1. DOOMの実行時にもLVGLのGUI処理タスクは並行して走らせておく。
  2. GUI処理タスクが画面をタッチされたことを検出したならば、DOOMタスクの実行を休止し、メニュー画面を表示する。LVGLタスクは、DOOMの画面表示には関与していないので、画面に変更があったのは、メニュー表示の部分だけだと思い込んでいる。そのため、メニューに相当する矩形部分だけの表示が更新され、残りの部分にはDOOMのゲーム画面画像が残ってくれる。
  3. メニューの選択が終了したならば、DOOMタスクの実行を再開する。DOOMの画面更新処理は毎回全画面の書き直しを行うので、LVGLが表示したメニュー部分もすぐに書き直される。

本来であれば、DOOMの画面更新処理部分をLVGLの描画機能を使って処理するのが全体の構造としてはキレイになるのですが、DOOM画面表示処理では、320x240から480x320への拡大処理とL8からRGB565へのカラーフォーマット変換をDMA2Dを用いて行っています。LVGLで処理させるようにすると、LVGL v9ではDMA2Dがサポートされていないこともあり、画面の更新が遅くなってしまいます。

LTDCを使う場合には、メニュー画面を表示している間も、ゲーム進行は継続されますが、上記の方式ではゲーム進行が休止されるので、慌てずにチートコードの入力が行えます。上記の画面でiddqdを選択すれば、体力が100%になり無敵モードになります。

このようにチートコードの入力機能も用意してあるのですが、わたしが興味あるのはこのような機能の実現であり、ゲームのクリアにはさほど関心がないので、いまだにひとつのエピソードも最後まで到達したことがありません。。

 


TLV320DAC3203

2024-05-23 12:51:37 | DoomPlayer

秋月の新製品情報を見ていたら、Nucleo-U575ZI-Qが出ていることに気づいたのですが、4,800円もすることにビックリ。円安の弊害をあらためて痛感しました。これじゃ、EP32やRas Picoに人気が流れてしまう傾向は強まるばかりですね。

DoomPlayer Nucleo-U575ZI にコーデックを載せようとして検討した際にも、コーデックチップがとても高くなっていることに気付かされました。TLV320AIC3204あたりが900円もする。そんななか、200円台で買えるTLV320DAC3203を見つけたので、これを使うことにしました。名前が示すようにTIの製品分類ではAudio CODECではなくAudio DACになっているのですが、アナログ入力やデジタルマイク入力も受けられるようです。96Kとか192Kのようなハイレゾオーディオには対応しておらず48KHzが上限のDACですが、DoomPlayer では44.1KHz 16bitステレオの音楽データをヘッドホンへの出力ができれば良いので、これで充分です。

DAC3203はDVddとして1.8Vが必要なので、NJM12877F18を載せてあります。アナログ電圧(AVdd)は内蔵LDOで生成するという使い方にしたので、AVdd端子はパスコンをつないだだけです。

STM32U575側では、SAIを使ってデジタルオーディオデータを送信。HSI 16MHzからPLLを使って生成した11.29MHzをMCLKとしてDAC3203に供給しています。この周波数は、44.1KHzの256倍になっています。DAC3203のReference Guideを参考にして初期化をおこなってから実際に音を出してみると、イヤフォンからはとても大きな音が出てきてびっくり。レジスタ設定を確認してみるとディフォルトのPowerTune ModeはPTM_P3になっており、アナログ出力の振幅が大きくなるようです。PTM_P1に変更することで、イヤフォン向けの大きさになりました。


新基板を作成

2024-05-15 12:50:34 | DoomPlayer

しばらくぶりの更新ですが、この1ヶ月の間にNucleo-U575ZI用の基板を作り直していました。

当初は使用する部品数を最低限に抑えて、簡単に作ることをひとつの目標としていたので、音の再生にはSTM32U5のDACを用いていました。その目的は達成することができて、音楽の再生もDOOMのゲームの実行もできるところまではできたのですが、実際に音を聞いてみるとやはり12bitのDACでは高域がカットされてしまうので、音の厚みが欠けており満足のできるものではありませんでした。

そんなわけで、部品数は増えてしまうけれども、やはりCODECを載せることに方針転換。基板を作り直しました。CODEC制御のためにSAIとI2Cを使う必要が生じたので、それに伴いSTM32U5側のピン割り当ても一部変更せねばならなくなりました。ひと通り動くようになったら、回路図とソースコードを開示するつもりです。


タスク構成 -- その2

2024-04-14 15:23:02 | DoomPlayer

前回の記事でタスク構成について書きましたが、その際にはCMSIS_OS2のAPIを使ってタスク情報を取得していました。DoomPlayerでは自分で書いたアプリ部分ではCMSIS_OS2のAPIを使っているので、自分が作成したタスク情報はこれで全て取得できているのですが、使用しているライブラリ部分でタスクが生成されていると、その情報は取得できていませんでした。

そこで、改めてFreeRTOSレベルのAPIを使ってタスク情報を取得するように変更しました。具体的にはuxTaskGetSystemState()を使用しています。また、タスク名に続いてそのタスクの優先度も表示することにしました。スタックサイズについては、ワード単位で表示されています。

この変更によりFreeRTOS内部で作成されているIDLEタスクとタイマー処理用の Tmr Svcタスクが表示されるようになりました。lv_conf.h において ''#define LV_USE_OS LV_OS_FREERTOS'' を指定するとlvglDrawという描画処理用のタスクも生成されるのですが、不必要に大きなスタックが消費される上に、タスクの優先度が高く設定されてしまい、他のタスクとの連携の観点で問題が生じするため、LV_OS_NONEを指定して使っています。この問題は、現在のlvglのgithub masterでは修正が加わっているようなので、次のリリースに期待したいところです。