2019年2月17日日曜日

PICのPWMで音楽再生2

前回、古いPICマイコンで大惨事になったので、比較的新しいPICで挑戦することにした。
PIC16F1619というもの。


3.3Vで動くしPIC内蔵OSCが32MHzまでいけるので部品点数がかなり減った!!
あとは
  • 乾電池で動くようにする
  • ボタン操作などで再生を切り替える
  • LEDなどの装飾
  • いい感じに収納する
をすればオモチャとして使えると思う

ソフト

ソフトの書き方も今風のやり方?にした。
MCC(MPLAB® Code Configurator)というもの積極的に使用する。
チュートリアル
http://microchipdeveloper.com/mcu1101:start
https://www.microchip.co.jp/download/dl_download.php/ID=17399660df745a6b64cd99d30b56a30b809e6694/
が大変参考になった。
日本語の情報はうまいこと見つけられなかった。
みんなArduinoとかSTMに移行したのかな。寂しいね。

MCC

基本的には、前述のチュートリアルの通り。
MCCプラグイン使用時は以下の感じ


困ったこと

PIC16F818のときには使いたい機能とピンに制約があったのだけど、
こちらは、ある程度自由に割当ができる。その分、悩むことも多い。。。
ファイルが自動生成させるので、それに従ってコーディングする必要がある。
統一した書き方ができて良いのだけど、ちょこっとしたものを書くのに、複数ファイルを行ったり来たりするのは、頭が付いて行かない(笑

良いところ

ピン割当がビジュアライズされてわかりやすい。
また、UARTの通信速度やタイマーやPWM設定で計算がかなり不要になった。

移植

基本的には、MCCのおかげであまりマイコンの差異を意識しなくて済んだ。
クロックが32MHzになったけど、TMR0の周期は8KHzと指定すればレジスタの設定を計算してくれるし。
SPIのクロックがOSC/4なので8MHzになったので、読み込みに余裕が生まれたはず。
20MHzの時は、コマンド+アドレス 計4B データ8Bで合計12Bを読むのに約273usとなった。
データ1Byteあたり約34usなので、約29kHzだった。
一方、32MHzになったので、単純に5/8・・・約170usになると思いきや、約102usになった。なぜ??
データ1Byteあたり約13usなので、約78kHz。


なので、音源のサンプリングレートを16kHzにしてみた。
すごくクリアになった・・・。
PWMが31.25kHzなので、32kHzにはできないね。どんな感じになるかは試してみたいけど。
ちゃんと計算してなかったけど、記録可能時間は、
2MByteのフラッシュ(8bit210241024 = 16,777,216bit)なので16,777,216 / (8bit16kHz) = 131.072s 約131秒・・・2分11秒くらい。

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

動作確認


こんな感じ