2019年2月7日木曜日

古いPICのPWMで音楽再生

子供用の音楽が鳴るオモチャとか作れたら素敵やん。と思って
本当に軽い気持ちで手を出してしまった。


だって、他の方はシンプルに出来ているんだもん。。。
http://manpuku-koji.hatenablog.com/entry/2017/11/23/104741
http://www.asahi-net.or.jp/~rn8t-nkmr/family/pic/vc/index.html

動機

FONから剥ぎとった2MBのフラッシュメモリが何個か余っているので、
有効活用できないかと思った。だって2MBだよ2MB!音楽なら1曲くらい入るんじゃない。
というもったいない精神から始めてしまったので、軽いはずの試作が上の写真みたいに大惨事になった。
なぜかというと・・・
  • 使ったPICマイコンが3.3Vに対応してなかった。5Vと3.3Vが必要
  • 5V->3.3V変換回路が必要
  • 内蔵OSCは8MHzが上限で、PWM周波数が足りない。 外付けOSC追加
  • 音が小さかったので、増幅追加
    とほほ
3.3V対応のPICマイコンで、内蔵OSCが20M以上あれば、こんな苦労しなくてよかったのにー

使用部品と回路

  • フラッシュメモリ MX25L1605
  • PICマイコン PIC16F818
  • オシレータ20MHz
  • 3.3Vレギュレーター
  • 5->3.3V変換用 VHC244
回路図がこちら。もう大惨事。


はまったこと・メモ

ダイオードのレベル変換はMHzクラスには向いていない

これになかなか気付けなくて、フラッシュからの応答が無かったり、化けたりして
フラッシュ交換したり、電源変えたり大変だった。
ずっとロジアナで見ていたので、余計にドツボにハマった。
以下のようにオシロで見れば一発なのにね。
ダイオードのレベル変換

VHC224のレベル変換


よく調べてから実行しよう
http://kosakai.world.coocan.jp/change_3_3V_5V.html

Zeroplusのロジアナはlinuxで使える

Zeroplusだけじゃないと思うけど、PulseViewで自動認識してくれた。
しかもSPIプロトコルも解析できた。すごいね。
いままで、MBEWAREのロジアナを使用していて、そのためにwindows環境が必要だったのだけど、これからはlinux環境でいけそうだね。
ただ、パターンジェネレータ機能はどうしようもないか・・・。

ソフト

ブロック図

ブロック図というか動作イメージ

PWM 周波数とデューティの計算

データシートとにらめっこ、すぐに忘れそう・・・。
PWM Period = [(PR2) + 1] • 4 • TOSC • (TMR2 Prescale Value)
PWM Duty Cycle = (CCPR1L:CCP1CON<5:4>) • TOSC • (TMR2 Prescale Value)
今回は20MHzのオシレータで、分解能が8bit確保できて、可聴域以上のPWM周波数にしたいので
PR2は255が必要*で、PWM周波数はPWM Periodの計算式から
(*CCP1CON<5:4>を駆使すれば、PR2は63でも良いような気がするけど、簡略化のために、CCPR1Lに読み込んだデータを入れるだけで良いようにしたく、今回は255で計算した。次回は63で試してみよう。)
プリスケーラ 周期[us] 周波数[kHz]
1 51.2 19.53125
4 204.8 4.8828125
16 819.2 1.220703125
プリスケーラを1に設定して、19.5kHzの周波数とする。
次にデューティは簡略化のためにCCP1CON<5:4>を0b00とした。
すると計算は簡単でCCPR1Lのみで、26とした場合は、約10%になる。

SPI

Masterモード時のCS

てっきりSlave Select (SS) RB5が使えるのかと思ったけど、これはSlaveモード専用みたい。
そして、SPI使用時にRB5は出力設定できないのか、意図した動きにならなかった。
仕方がないので未使用だったRB0をSSとして使うことにした。

flashROMからの連続読み込み

SPIの読み込みは最速でOSC/4なので、今回は5Mbps程度となる。つまり1クロックあたり0.2usとなり8bitのデータ転送には1.6usという計算になる。
単純に考えるとflashROMからの読み出しは[READ 03h][AD1][AD2][AD3]と[DATA]の計5B必要になるため
1.6*5で8us/Byte・・・125kHzくらいと思いきや
実測すると5B転送するのに124usくらいかかっている。むーん。
これだと、8kHzぎりぎりなので再生速度揺らいでしまうかもしれない。
MX25Lのデータシートには、CSをLOWのままでクロック与え続けると、アドレスを増加させて読み込み続けると記載があったので、1度に8Bデータを読むようにしてみた。
すると、コマンド+アドレス 計4B データ8Bで合計12Bを読むのに約273usとなった。
データ1Byteあたり約34usなので、約29kHzとなり十分に余裕がある。

リングバッファ

flashROMからの読み込みが十分速いので、不要な気もするけど32Bのバッファ用意した。
125us * 32 = 4ms の余裕が生まれるハズ。効果は未確認。

音源の作り方

ようやく音源の準備。ブログとかyoutubeに出していいかわからないので、そういう使用がOKな音源を探す。
例えば、d-elf.comさんのところにある「蒼い月 初音ミク・アペンド Blue Moon/HATSUNE MIKU Append Ver.」の場合。
Blue_Moon_MIKU_Append.mp3で2.9MBある。これを8kbps 8bit モノラルとしてデータ部のみ保存する。

Audacityで

cuiなコマンド1発に憧れるけど、まずはguiでやってみる。そうAudacityで。

音源を8kbps 8bitモノラルに変更

  1. トラックを選択してから[トラック]→[ステレオからモノラルへ]を選択
  2. ウィンドウ下方の[プロジェクトのサンプリング]で8000Hzを選択

データ部のみ保存

  1. 「選択したオーディオを書き出し」
  2. 「その他の非圧縮ファイル」、ヘッダ:RAW(header-less)、エンコーディング:Unsigned 8-bit PCM
これでOK。約985kBのデータができた。
内容を確認するときは、[ファイル]→[取り込み]→[ロー(Raw)データの取り込み]

flashROMに書き込む

この前やったflashROMの書き換えが早速役に立つ。
dd if=/tmp/miku.raw of=/tmp/2m_base.img ibs=2M conv=sync
flashrom -p linux_spi:dev=/dev/spidev0.0 -c “MX25L1606E” -w /tmp/2m_base.img

動作確認


こんな感じ


0 件のコメント:

コメントを投稿