2016年12月18日

WAVE/PCM再生: @70円のPIC16Fで8bit PWM player音楽再生 2017

WAVE/PCM再生: @70円のPIC16Fで8bit PWM player 音楽再生 2017
* はじまり
* Download (2017/02/18) up!
* ブレッドボード図
* 対応マイコン
    コードサイズ:
    最小サイズ:

[仕様]
* SDカード仕様
* Wave/PCMデータの形式
    曲間ノイズとWAVヘッダ/音楽情報(アルバム画像)チャンク等:
* Wave/PCMデータ一括変換ソフト
* 再生操作仕様
    (1) 動作:
    (2) Btn SW(ボタン・スイッチ)仕様
    (3) LED インジケータ(Indicator)
* 再生順序

[制作]
* 回路図
* Pin配列図
* プッシュ・スイッチ
* 制作上の注意点

* 処理速度についてのメモ
* SPI Clockについてのメモ
    PIC18F14K50:
    PIC18F26J50:
* 使用リソース

[コンパイル]
* コンパイルと書込み
    バッチファイル m.batでコンパイル:
    makeを使ったコマンドライン・コンパイルの方法:
    準備
    コマンドライン・コンパイル:
    PICへの書込み:

[その他]
* 雑多なメモ
* 使ったツールのメモ
    WinHex:
    Binary Edit Bz:
* その他の関連作例メモ
    データレコーダーのエミュレータを作ってみた (その6):

* はじまり
ひょんなことから、このページを発見したのだった。
WAVE PLAYER FOR PIC16F877A.!
microC用のサンプルコードでPIC16F877Aで動作するWAVE PWM Playerだ。
試しに、無料版のmicroCでコンパイルしてみると、
なんと、たったの
Flash: 1755word
SRAM : 150byte
で、fs=22.1KHz,stereoのWAVファイルがFAT16のSDカードで再生できるサンプルコードだった。
これは面白そう ということで、
microCのお試し版は2000wordまで使えるので、さっそく より高速で動作するPIC16F1827に移植して
みたのだった。これならfs=44.1KHz,stereoが再生できるはず。。。
ところが。。。。
これがさっぱり動かない。動かない、動かない。。。
よくよく調べていくと、
「これじゃ動かない !」 (オイ

決め打ち要素がいくつか障害になって、そのままでは動かないのだった。
orz
で、結局 ChaNさんのこのページを熟読することに。。。
FATファイル システムのしくみと操作法
それにしてもChaNさんの解説がすばらしく分かりやすい。(^^)/
感謝! m(__)m

その後、microCのお試し版のままだと、容量不足でprintf系デバッグができないし、
そもそも microCにはprintf関数がないのだ(簡易型の代替関数を使う)。orz
しかたがないので、
XC8に移植、MPLABXでデバッグしてなんとか音が出るようになったものの、
XC8の無料版はコードサイズが肥大化傾向で、実行速度もあまり速くないこともあり、
結局、
超効率コンパイラのjalv2に移植することにした。
jalv2の実力を確認する良い機会でもあるのだ。

で、最初はFAT16バージョンだったが、 今時FAT16対応のSDカードなんて入手が難しいので、(注7)
FAT32にも対応してみた。
さらに、
最近、ある程度充実(秋月電子)してきた最新のPIC16F Enhanced midrageで
お値打ち感のあるものを選んで対応してみた。

* Download
hexフォルダにHEXファイルがあるのでPickit3で書き込みます。
(2017/02)
16f-pwm-wave-player_v8.6-2017-02.zip

* ブレッドボード図
後述の回路図を参考に作ってみた。
部品番号は適当に割り振ってあります。
実際に作ったものに近い感じ。(全く同じではありません :-)
pic16f18313-sd-wave-player_breadborad-2017-2.png
上のSD Socketの端子名は、SDカード側の端子名。

* 対応マイコン
Enhanced midrageのPIC12F1系/16F1系と、PIC18Fのみで動く。
コードサイズ:
    ざっくり、
        Flash: 1600 word ~ 1800 word
        SRAM : 150 byte
    程度で、マイコンの種類や機能オプションによって変動します。
最小コードサイズ:
    16F18313/FAT16限定/SW(ボタン・スイッチ)なし、 という条件で、
        Flash: 1474 word
        SRAM : 143 byte
    を記録。
PICSD card:SDSC/SDHC, FAT16/32, Long filename対応
PIC名 価格(注1) MIPS値 PPS Flash/SRAM Pin数 動作の
可否
出力 Sampling
周波数
LED Dev.Rev
8pin
PIC12F1840 115円 8MIPS - 4KW/256B 8pin O mono 44.1KHz - 5
PIC16F18313 70円(税別) 8MIPS O 2KW/256B 8pin O mono 44.1KHz - 2004
14pin
PIC16F1455 160円 12MIPS - 8KW/1024B 14pin O stereo 44.1KHz O ?
PIC16F1705 100円 8MIPS O 8KW/1024B 14pin O stereo 44.1KHz O 2002
PIC16F1764 120円 8MIPS O 4KW/512B 14pin O stereo 44.1KHz O 2002
PIC16F1825 140円 8MIPS - 8KW/1024B 14pin O stereo 44.1KHz O 4
PIC16F18325 100円 8MIPS O 8KW/1024B 14pin O stereo 44.1KHz O 2045
PIC16F18326 130円 8MIPS O 16KW/2048B 14pin - stereo 44.1KHz O -
18pin
PIC16F1827 135円 8MIPS - 4KW/384B 18pin O stereo 44.1KHz O 4
20pin
PIC16F1459 180円 12MIPS - 8KW/1024B 20pin O stereo 44.1KHz O 1003
PIC16F1619 150円 8MIPS O 8KW/1024B 20pin O stereo 44.1KHz O 2004
PIC16F1709 150円 8MIPS O 8KW/1024B 20pin O stereo 44.1KHz O 2002
PIC16F1769 - 8MIPS O 8KW/1024B 20pin - stereo 44.1KHz O -
PIC16F1829 160円 8MIPS - 8KW/1024B 20pin O stereo 44.1KHz O 4
PIC16F18346 160円 8MIPS O 16KW/2048B 20pin - stereo 44.1KHz O -
PIC18F14K50
PIC18F13K50
210円
200円
8MIPS
(12MIPS)
(注4)
- 8KW/768B
4KW/512B
20pin O mono 44.1KHz O 6
28pin
PIC16F1938 190円 8MIPS - 16KW/1024B 28pin O stereo 44.1KHz O 2
PIC18F26J50 260円 12MIPS 32KW/3776B 28pin O stereo 44.1KHz O 4
* SDカード仕様 (1) SDカードはSDFomatterで「クイックフォーマット」をした直後に https://www.sdcard.org/jp/downloads/formatter_4/ wavファイルをSDカードのルートにコピーしてください。 言い換えると、SDカード上のクラスタ配列にフラグメントが発生していない状態が必要です。 コピー後に "削除、またコピー"等は音飛びの原因になります。 (2) SDカードは、SDSC/SDHC FAT16/FAT32に対応してありますが、 こちらで試したのは、 (a) 2GB/SDSC/FAT16 1種類 (b) 16GB/SDHC/FAT32 3種類 の4種類のSDカードです。 MMCは非対応です。 すべての SDSC/SDHC FAT16/FA32 カードで動作するかどうかなんて全く分かりません。xD といいつつ、ほとんど大丈夫じゃないかと踏んでたりします。(オイ (3) ファイル名はショートファイル名のみ、ロングファイル名のみ、二つの混在が可能です。 漢字ファイル名も問題なさそうでした。 (4) WAVファイルは「アーカイブ属性(A)」になっている必要がありますが、 通常はそうなっているずなので気にする必要はないと思われます。 * Wave/PCMデータの形式 再生可能な「*.WAV」ファイルは、 上記表から例えば「mono」、Sampling周波数(以下fs)=44.1KHzと読み取れた場合、 その通りのデータ形式である必要があります。 mono出力のものにstereoデータを与えても正しく再生できません。逆も同じです。 PCMデータは8bitです。 その辺にあるwavファイルを持ってきても恐らく16bitなので再生できません。 後述の変換ソフトを使って適切なデータを作る必要があります。 曲間ノイズとWAVヘッダ/音楽情報(アルバム画像)チャンク等: WAVヘッダ情報は見ていません。先頭の44バイトを読み飛ばしているだけです。 従って、44バイト直後に音楽情報チャンクがあるとそのまま再生してしまうので 「曲間ノイズ」が発生します。 また、数十キロバイト・オーダーでアルバム画像がWAVファイルの最後に付加されている場合も、 曲間で「比較的長く大きな ザザーッ!」というノイズが発生します。 "先頭のWAVヘッダ(44バイト)とPCMデータ"以外の情報が、 ツール等でカット可能ならカットしたほうが 良いです。 * Wave/PCMデータ一括変換ソフト いつもは「foobar2000やSoX」を使用していますが、 今回は「mono」データ化が必要になったこともあり、別のソフトを探してみました。 Switch Audio File Converter http://www.nch.com.au/switch/index.html 変換は「Output Format:」に「.wav」を選択、その右の「Options」で、 Settings: Customにすると「Format:」の部分で色々選択可能になります。 Encoding:は「PCM Uncompressed」でOK. 今回偶然見つけて使ってみただけなので詳細は不明、 金払えメッセージが毎回のように出てきて、:D orz なところもある。 * 再生操作仕様 (1) 動作: 電源投入後、ルートフォルダにある拡張子「.WAV」ファイルを順に再生していきます。 最後のファイルを再生した後、また最初のファイルから再生を開始します。 (2) Btn SW(ボタン・スイッチ)仕様 Next: 再生中に「一回クリック」すると次の曲に飛びます。(指を離したタイミングで動作します) Pause: 再生中に 「1.x秒以上」押し続けるとポーズします。ワンクリックで解除します。 (x=0...5 のどれか。今はx=2) Power Off: 4秒以上押し続けるとパワーオフしようかなと思いましたが、 現状ではあまり意味がないので何も起こりません。:D (3) LED インジケータ(Indicator) LEDが付けられる14Pin以上のマイコンでは、 再生中: LEDがゆっくりめに点滅します。 Pause中: LEDが比較的高速に点滅します。 LED疑似PWM(Pseudo PWM): LEDがチカチカすると「目もチカチカ」してしまうので、xD 目に優しいLED疑似PWM点滅に変更しました。 副作用として、 (1) コードサイズが増加した。 orz (2) LEDの電流と配線具合によってはPWMノイズが聞こえてしまいます。orz コンパイル・オプションの変更により、軽量で低ノイズなLEDチカチカ版に切替可能です。 * 再生順序 SDカード上に書かれた順で再生順が決定します。 再生順序が大切な場合はクイックフォーマット後、1個づつ手動でコピーするか スクリプト等で順序決めしてコピーさせるのが確実かも。 * 回路図 回路図は一部のみ存在します。(PIC12F1840/PIC16F18313,PIC16F1827) 回路図がないマイコンの場合、同梱されている「pin_map.txt」を参照して配線して下さい。 pic16f18313-sd-wave-player_schematic-2017.png PWM_OUTが音声出力端子。 FOSC=48MHz(12MIPS)で動作させているマイコン(PIC16F1455, PIC16F1459, PIC18F26J50)以外は 出力電圧が小さいので、アンプ類(PCのオーディオ入力、簡易オーディオアンプ等、ヘッドフォンアンプ、TRスイッチング回路等)をつないだほうが良い。 ということを念頭に置きながら、以下は一般的な話、 (1) パソコンのオーディオ入力につなぐなら、おそらく直結でOK。心配なら10uFを経由させる。 (2) 8オームの100円スピーカにつなぐなら100uFを経由させる。自分は試してない。 その後、2000円のスピーカで試したけど、音は小さかった。 (3) 一般的なオーディオアンプにつなぐなら、ローパスフィルタを入れたほうが無難かも。 * Pin配列図 SD cardのピン配列. ArduinoとかNucleoとか、今回は無意味。:D
-- /* SD card pin
-- Pin side
-- --------------\
--         9     = \    DAT2/NC
--             1 ===|   CS/DAT3    [CS]
--             2 ===|   CMD/DI     [DI]
--             3 ===|   VSS1
-- Bottom      4 ===|   VDD
-- View        5 ===|   CLK        [CLK]
--             6 ===|   VSS2
--             7 ===|   DO/DAT0    [DO]
--         8       =|   DAT1/IRQ
-- -----------------
--
--                                         Arduino      NUCLEO-F411       NUCLEO-F030R8
-- Logo side
-- -----------------
--         8       =|   DAT1/IRQ
--             7 ===|   DO/DAT0    [DO]     D12           D12/PA_6           D5/PB_4
--             6 ===|   VSS2
-- Top         5 ===|   CLK        [CLK]    D13           D13/PA_5           D3/PB_3
-- View        4 ===|   VDD
--             3 ===|   VSS1
--             2 ===|   CMD/DI     [DI]     D11           D11/PA_7           D4/PB_5
--             1 ===|   CS/DAT3    [CS]     D8            D10/PB_6           D10/PB_6
--         9     = /    DAT2/NC
-- --------------/
-- */
PIC16F18313とPIC16F1840のピン配列は全く同じ。
-- /*                   PIC12F1840   4KW/256B
--                      PIC16F18313  2KW/256B
--                       ---__----
--           3.3V--- VDD|1       8|VSS --- GND
--      PWM CCP1 --- RA5|2       7|RA0 --- [PGD] - SDO
--            CS --- RA4|3       6|RA1 --- [PGC] - SCK
--    SW --- [/MCLR]/RA3|4       5|RA2 --- SDI
--                       ---------
-- */
PIC16F1827等、UARTが同時に使用可能な多ピンPIC(18pin以上)では、UART出力を有効にしてコンパイルすると、 再生中のファイル名を115200bpsでUARTに出力します。(デバッグ用途) (ショートファイル名表示なので "元がロングファイル名" の場合、結構謎な表示になったりします。)
--  /*                  PIC16F1827  4KW/384B
--                       ----_----
--     TEST PORT --- RA2|1      18|RA1
--   PWM(L) CCP3 --- RA3|2      17|RA0
--   PWM(R) CCP4 --- RA4|3      16|RA7
--    SW --- [/MCLR]/RA5|4      15|RA6 --- SDO1
--           GND --- GND|5      14|VDD --- 3.3V
--           LED --- RB0|6      13|RB7 --- [CSPDAT]
--          SDI1 --- RB1|7      12|RB6 --- [CSPCLK]
--      UART_RX ---- RB2|8      11|RB5 --- UART_TX
--         SD CS --- RB3|9      10|RB4 --- SCK1
--                       ---------
--             Playing:  26.2mA   current consumption
--             Sleeping: 22.0mA
--  */
pic16f1827-wav-sd-player-schematic-2017.png * プッシュ・スイッチ (Btn sw) ボタン・スイッチと言ったり、 プッシュ・スイッチと言ったり、 自分の中では明確に区別してなかったりするので、適当に呼称してますが、 全部同じもの。実際には タクト・スイッチか。(オイ 使用した操作用のスイッチは、 http://akizukidenshi.com/catalog/g/gP-01282/ を使用している。これ以外のスイッチを使った場合、別途デバウンサが必要になる可能性を 否定できない。上記スイッチの場合デバウンサは不要です。 シュミット・トリガ入力の/MCLRにSWが繋がっているので... 参考: http://www.marutsu.co.jp/pc/static/large_order/1405_311_ph * 制作上の注意点 全体: /MCLR(リセット)端子をボタン・スイッチ入力に使っている関係上、 Flash書き込み後にリセットが正しくかかりません。 従って、一旦電源をOFFした後、ONする必要があります。 8pin PIC: 上記に加えFlash書き込み後に正常動作させるため、Pickit3の配線を すべて取り払う必要があります。 LEDとスイッチ: この2つは付けなくても動作します。 その場合、無限ループ再生動作のみとなります。 * 処理速度についてのメモ 割り込み内でセクタ切り替えをしている関係上、速度の遅いSDカードだと 処理時間が超過してセクタ切り替えのたび(5.8msec=22.3usec x 256(ステレオの場合))に前回と同じデータが出力 されてしまう。 そうなっても、実際音を聞いたときにわかるかといわれると、 比較するのが難しいのでなんとも言えない。 変わらない気がする。。。 気がす。。。 * SPI Clockについてのメモ SPI Clockは速ければ速いほど良い。 FOSC=32MHzの場合、FOSC/4=8MHzが最高クロックになるが、データシート上は 5MHz前後が限界値の様だ(PIC18F14K50しか確認していない) (要再確認) 最初にFOSC/4のSPI Clockで動かしてみて動作しないマイコンは、 6MHz or 4MHzに落としてある。 ブレッドボード配線なので、半田配線に変えればSPI clock=8MHzで動く可能性も否定できない。 あるいはSPI系の内部プルアップをやめて、外部に50Kオームから100Kオームの プルアップに変えてみる手もあるが、そういう問題かどうかは未確認。 PIC18F14K50: FOSC=48MHzの時,SPI clock=12MHzの波形は「なまった三角波」の様だったが、 音楽再生に支障はなかった。「よくこれで再生できてるよなぁ〜」って感じでした。 最終的に内部発振モードFOSC=32MHz,SPI clock=8MHzで使用した。 PIC18F26J50: FOSC=48MHzの時,SPI clock=12MHzの波形が「かなりきれい」で、 PIC18F14K50との差は歴然だった。 さすがは、USBやDMAが付いてるだけのことはある、という感じか。 内部発振モードFOSC=48MHz,SPI clock=12MHzで使用した。 * 使用リソース Timer1(16bit): 10msec tickのシステムタイマ Timer2(8bit) : PWM周期発生用 CCPx/PWMx : PWM出力ポート SPI系 : SD card 制御用 UART : デバッグ出力用 (optional = false(デフォルト値)) TEST PORT : デバッグ出力用 (optional = false) LED Port : 動作表示用 (optional = 8pin PICを除いて true) Btn sw Port : Play,Pause切換え(optional = true) (optional): コンパイル時に有効・無効を選択可能 * コンパイルと書込み HEXファイルがあるので、無理にコンパイルする必要はありません。 JalEditを使ってmain.jalを読み込めばコンパイル可能ですが、 JalEditはほとんど使わないのでここを参照してください。 Tools - Environment - Optionsの'Path of JAL Lib folder(multiple....)' の最後に「;lib」を追加する必要がある。 バッチファイル m.batでコンパイル: (1) m.bat内のcompiler_rootJalv2コンパイラ・ルートフォルダ(jallib-full-1.x.x)までのパスを設定します。 (2) set device=16F1827 のマイコン名の部分を適宜変更します。 MS-DOSコマンドプロンプト上でm.batを実行すればコンパイル可能です。 上記の場合、 sd-wav-player-16F1827.hex というファイルが生成されるので、Pickit3で書き込みます。 makeを使ったコマンドライン・コンパイルの方法: 準備 (1) msys2のコンソール上でコンパイルするのがデフォルトです。(msys/MinGWでも恐らく可(未確認)) 最低限"make"コマンドが必要です。 msys2のインストールや使い方は省略します。 (2) Makefile内のjal_root, jal_sysJalv2コンパイラまでの絶対パスなので 個々人の環境に合わせて変更します。 コマンドライン・コンパイル: 以下のどちらかでマイコンの品種を決めてmakeします (1) $ make device=16F1829 この場合、PIC16F1829マイコン用のコンパイルをします。 以下の(2)の設定に影響を受けません。 (2) $ make Makefile内の device=nnnnn 行を一つ有効にして makeします。(nnnnn=マイコン名) (注)マイコン名nnnnnに指定可能なのは、上記表に記載のマイコンみです。 (動作の可否が"-"となっているものを除く) PICへの書込み: 書込みはPickit3を使います。Pickit2は非推奨です。(注5) Makefile内のPickit3への実行パスは適切に変更しておく必要があります。 (1) $ make f とすると、Pickit3のコマンドライン版(MPLABX,ipecmd)を使って書き込みます。 (2) $ make f2 とすると、同様にPickit2(pk2cmd)で書き込みます。(非推奨) (3) $ make f3 はPickit3の別名コマンドの実験用です。 (例) $ make f device=16F1829 PIC16F1829用にコンパイル後、Pickit3を使って書き込みます。 * 雑多なメモ (1) mono/stereoの自動切り替えは、割り込み内の処理やコードサイズが増えるので 省略したが,付いてた方が便利かも。 (2) Power SW機能(sleep, wake up)は省略したが、MOS-FETのHigh sideスイッチで SDカード電源を制御可能にすれば付けても良いかも。今回は省略。 (3) 一部を除いて出力音量が小さいのは、PWMタイマの分周比が今ひとつ荒いのが原因。orz (4) コードサイズは、もう少し減らせる可能性はあるんだけど、 上の表から分かるように、100円で FLASH:8Kword,SRAM:1KbyteのPICがあるので、 もういいかなぁ〜 って感じ。:D (5) 8ピンマイコンでWAVプレイヤーをつくってみた【電子工作】 視聴にはログインが必要。orz こちらの方は、PIC12F1822(Flash=2Kword,SRAM=128byte)で制作している。 実際の使用量は1751word/95byteらしい。スゴ。 * 使ったツールのメモ WinHex: http://www.x-ways.net/winhex/index-m.html SDカード内の構造をパソコンから見るツール。 管理者権限で実行する必要があります。 ディレクトリ・エントリや相対アドレスで閲覧可能。 MBRは見れない気がする。 Binary Edit Bz: http://forest.watch.impress.co.jp/library/software/binaryeditbz/ バイナリエディタ、ビューア。便利 * その他の関連作例メモ ネット上で似たような作例がないか探索してみたのでメモしておく。(注6) データレコーダーのエミュレータを作ってみた (その6): ATtiny861AとSDカード http://kitahei88.dtiblog.com/?i&no=84 (注1) 2016/12月時点の秋月電子価格がベース。端数の表現はテキトーです。 特に表記がない場合、税込み表記。 (注2) 実際の値はコンパイラやソースのバージョンに依存して変動する。 (注4) マイコンは内蔵クロック使用で8MIPS(FOSC=32MHz)動作させている。 PIC18F13K50は所有していないが単に容量違いなので動くでしょう。 (注5) 仮に有志作成のアップデータを使ってPickit2で書込めたとしても動作しない可能性が高い。 Pickit2からの書込みでPIC16F1619は動作しないことを確認した。 (注6) ChaNさんの作例は有名すぎるので省略します。(^^; (注7) 入手できなくはないけど、FAT32のほうが圧倒的に値段が安い。
posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | PCM/WAVE | このブログの読者になる | 更新情報をチェックする

2016年03月22日

WAVE/PCM再生: Arduino: AVRで8bit PWM音楽再生 2016

WAVE/PCM再生: Arduino: AVRで8bit PWM音楽再生 2016
* はじまり
* ChaNさんのFatFs
* プチ音の消去
* Arduino NanoでSDカード,5V:3.3Vレベル変換接続
    抵抗でレベル変換 バツ:
    ダイオードでレベル変換 ○△:
    残念ながら:
* 動作可能ボード
* Arduino Wave PWM Player Lite版 仕様
    概要:
WAVファイル仕様:
    機能:
* SDカードの速度問題
    44.1KHz(以下)/8bitに変換する:
* SDカード速度測定機能
    使い方:
* SDカード シールド対応
* 実体配線図
    出力の高域カットフィルタ:
    Arduino(ATmega328p with 16MHz crystal) UNO/Nano/etc. :

* Download v1.3 (2016/04)
    書き込み方:
* 動作確認

* avr-gccのバージョン
* Petit(ぷち) FatFs

* その他のWave player
    TMRpcm
    SimpleSDAudio

* はじまり
AE-ATmega/AVR: 8bit PWMの音 / PCM/WAVE再生
から3年。
47秒周期くらいのクラスタ境界で「プチ音」がするために見捨てられていたのを復活させてみた。

* ChaNさんのFatFs
http://elm-chan.org/fsw/ff/00index_j.html
前回は
R0.09b    (C)ChaN, 2013 を使っていて,今回は
R0.11a    (C)ChaN, 2015 という最新版を使ってみた。
disk_read()関係がかなり高速化されている様でビックリしました。
ATmega328p 16MHz でSDカードのリードテストしたら 720KB/sec 出てた。(OoO)/
古い版だと"512バイト読み出し直前の準備期間"が固定長で結構時間がかかっていて,
低速でSRAMが少ないマイコンの場合,速度のボトルネックになっていたが,その部分が消失していた。
これは良い。

* プチ音の消去
でもプチ音に変化なし。orz
で,
ChaNさんのFatFs:AVR用のサンプル(ATmega64)をなんとかATmega328pに移植して音を聞いてみると,
(ChaNさんのサンプルもWAVE再生可能)
なんとプチ音なしだった。orz (オイ
ChaNさんのプログラムをいろいろ調べたところ :D
バッファーアンダーフローが起きた時に"前回のデータを出す"という部分があって
それのおかげでプチ音が消失しているのが分かった。
ちなみに,
移植ミスも否定できないけど,ChaNさんのは
約3msec周期で300usecの期間バッファーアンダーフローが起きていて,
この周期で約15回づづ前回と同じデータを出していたのだった。(OoO)
バッファーアンダーフローの対処がないとノイズだらけになるハズなんだけど。。。 
恐るべし,人間の耳 xD
今回はサンプルコードの解析が目的ではないので :D
そのうち調査してみるか。。。

で,
自分の方は47秒に一回程度なんだけど,上記バッファーアンダーフローに対応することで,
ようやくプチ音が消去できました。
(^^)/ (^^)/

「ごまかした」とも言う。(^^;
この部分はマイコンクロックを20MHzに上げればクリア可能と思われます。

* Arduino NanoでSDカード,5V:3.3Vレベル変換接続
前回は秋月のArduino Duemilanove互換ボード(AE-ATmega)を3.3V改造したものを使ったけど,
http://mpu.seesaa.net/article/399685555.html
今回は一般的な「Arduino Nano互換ボード」:D につないでみた。
従って,
SDカードをつなぐためには5V(Arduino側)と3.3V(SDカード側)のレベル変換が必要です。
参考:
しなぷすさんのハード制作記のページ
3-6.5VのArduinoと接続する方法
http://www3.big.or.jp/~schaft/hardware/hard/MGLCD_AQM1248A/page004.html

抵抗でレベル変換 バツ:
    ググると1.8KΩ:3.3KΩくらいでレベル変換しているのがあったのでやってみたけど,
    再生中に頻繁にリードエラーが起きて全然ダメでした。
    ブレッドボードだからアレなのはアレなんだけど xD
    orz
    SPIクロック8MHzなのでもっと速度を落とせばひょっとしたらそれなりの用途には使用可能
    かもしれないけど,波形を観測すると,とても使う気にはなれない。orz
    さらにググると抵抗値を下げている人がいて結構きれいな波形だったが,
    電流がものすごいことになっているので今回は未実験。
ダイオードでレベル変換 ○△:
    さらにググると, (オイ
    ダイオードでやっている人がいてこっちの方がよさそうだったので試してみたら,
    抵抗変換よりだいぶマシだった。
    というか今回の用途には問題なく使えた。(^^)/
    波形を見ると立ち上がりが悲惨な感じだけど,立ち下がりは問題なさそうな感じだった。
    電流も少なくて済むのでこれを採用しました。
    簡単だし,ダイオードは部品箱にあるのだった。
残念ながら:
    上のダイオード方式も手持ちのSDカードを全部試してみると
    一部のものはリードエラーが出て使えなかったので万能ではない模様。
    ちゃんとしたレベル変換を付けるのがベストなのは間違いなさそう。:D
    と,いうことでこの手の簡易型のレベル変換は高速クロックでは信頼度が
    低いことが分かりました。

* 動作可能ボード
マイコンがATmega328p,動作クロックが16MHzの互換ボード,
Arduino: UNO, Duemilanove, Nano, Mini, Pro 及び "素のATmega328pマイコン+16MHz水晶発振子"
等々でHEXファイルを書くだけで動作します。
(注) 素のATmega328pの場合,Fuseに適切に書き込む必要あり

* Arduino Wave PWM Player Lite版 仕様
概要:
Lite版なので曲の選択機能はありません。(^^;
電源ONか,SDカードが差し替えられると以下の順でフォルダを探して,
/music
/wav
/    (ルートフォルダ)
最初に見つかったフォルダ内のWAVファイルを順に再生して無限ループします。
次の曲には飛ばせるけど,前の曲には戻れません。(^^; (注1)
SDカード挿抜とかは見ていないので,電源ONのままmicroSDカードの抜き差しは非推奨ですが,
自分は自己責任でやってたりします。:D
WAVファイル仕様:
    foobar2000又はSoXでWAVファイルに変換されたものをターゲットにしています。
    これ以外で変換されたファイルは未確認です。
        PCM: 8bit / 16bit 
        Stereo/Mono
        fs(サンプリング周波数): 48KHz以下。
        こちらで確認したのはfs=8KHz,32KHz,44.1KHz,48KHzのWAV(8bit/16bit)ファイルですが、
        最低でもfs=22.05KHz以上で使用することを強く推奨します。
        通常は最も音質が良いfs=44.1KHzを推奨します。

機能:
    [パソコン上のUARTターミナル(TeraTerm等)から操作]
         次の曲に飛ばす :  [N], [ ](スペースキー)   
         再生ポーズ/解除:  [S], [P], [ESC](エスケープキー) 
                     一度押すとポーズし,画面に「P」マークが表示されます。
                     もう一度押すとマークが消えて再生再開します。
         曲の先頭に戻す:   [F]キー
                     再生中にこのキーを押すと,その曲の先頭に戻って再生を開始します。
         早送り(FF)/巻き戻し(Rewind): FF: ]キー Rewind: [キー 
                     再生音を出しながらFF/Rewindします。
                     最後までFFすると次の曲に行ってしまいます。(^^;
         音量ボリューム:  Up:[+ or .(ピリオド)], Down:[- or ,(カンマ)]キー で音量Up/Downします。
                     32ステップです。
         可変速再生: Speed Up:[U], Speed Down:[D], Speed Normal:[0]
                        高速側はあまりSpeed Upしません。
    [外部の押しボタンSWで操作]
        (1) 次の曲に飛ばす:  SWを一回クリック。(離した(0.5秒以内)タイミングで次の曲に飛びます)
        (2) 再生ポーズ/解除: SWを1秒以上押し続けると再生ポーズします。
                         手を離してSWをもう一回クリックするとポーズ解除されます。

* SDカードの速度問題
16ビット/44.1KHz/Stereoのファイルを再生するには, そこそこ高速なSDカードが必要になります。
手元に高速なSDカードがない場合以下の対応方法があります。
44.1KHz(以下)/8bitに変換する:
マイコンのPWM出力は8ビットの分解能しか使わないので,foobar2000で
44.1KHz(以下)/8bitにWAVファイルをコンバートしたものにすれば
低速なSDカードでもOKになる可能性大です。
今回の場合,8bitに落としても音質は変わりません。(^^;

* SDカード速度測定機能
SDカードのリード速度を計測する機能を付けました。
これでSDカード速度の絶対評価が可能になります。
使い方:
    音楽の再生中(or ポーズ中)に「t」キーを押すとリードテストがはじまります。
以下のようにリード速度が表示されます。
 [PCM]  S321601.WAV 32000Hz 16bit Stereo 26115412 Byte
  -----+-----+-----+---
  *****************
 [Read]: Testing 512 byte buffer: read performance...
 Done!
        Result: 314 KB/s

  [PCM]  S441601.WAV 44100Hz 16bit Stereo 66767804 Byte
  -----+-----+-----+-----+-----#-----+--
  *****
手持ちのSDカードのなかで,44.1KHz/16bitの読み出しで問題なく使えたSDカード。
リード速度 SDカード
332KB/sec Transcend 2G FAT SD @?
303KB/sec SanDisk 16G FAT32 UHS-I @6
302KB/sec Victor 4G FAT32 SDHC @4
294KB/sec Good-J 16G FAT32 SDHC @10
266KB/sec BUFFALO 16G FAT32 SDHC @4
(22.3usecの割り込みがガシガシ入った状態で速度計測しています) 44.1KHz(以下)/8bitデータならもっと遅くても大丈夫だと思います。 * SDカード シールド対応 以下のSparkFunとSeedStudioのSDカードシールドに対応。 チップセレクトが違うだけなので二つのチップセレクト端子を同時にパタパタさせてます。 持ってるわけでないので本当に動くかどうかは未実験。 SparkFun microSD Shield https://www.sparkfun.com/products/12761 SD Card shield V4.0 http://akizukidenshi.com/catalog/g/gM-09696/ http://www.seeedstudio.com/wiki/SD_Card_shield_V4.0 * 実体配線図 電源: Arduino Nanoの場合,3.3Vは外部から供給する必要があります。 3.3VはSDカード用なので100mA以上を供給可能なものが必要と思われます。 ダイオード: ダイオードは部品箱にありがちな適当なのでOKです。(オイ 一本1円で十分かと。 http://akizukidenshi.com/catalog/g/gI-07783/ ショットキ・バリア・ダイオード(SBD)でも大丈夫です。高いけど。 出力の高域カットフィルタ: この実体配線図はPC(パソコン)のAudio入力端子との接続を想定しているので省略してありますが, 一般のアナログアンプに接続するなら,以下のページの出力ローパスフィルタを入れた方が 良いです。(或いはもっとマシなフィルタ:-) http://mpu.seesaa.net/article/432426722.html
arduino-nano-wave-pwm-player.png
注意ポイント: 当然のことながら,SDカードは壊れてもおしくないものを使って下さい。 うちは2枚ほどダメになりました。(お〜〜〜い (爆 orz Arduino(ATmega328p with 16MHz crystal) UNO/Nano/etc. : 使用端子のメモ。pin番号は28pin DIPのもの。
  [ PWM ] 
         OC1A: PB1, 15pin, D9   : Audio Left
         OC1B: PB2, 16pin, D10  : Audio Right
  [ SPI ]      <Arduino>               <SD Card>
         MOSI: PB3, 17pin, D11         DI,  2pin
         MISO: PB4, 18pin, D12         DO,  7pin 
         SCK : PB5, 19pin, D13         CLK, 5pin
         CS  : PD4,  6pin, D4          CS,  1pin
         or
         CS  : PB0, 14pin, D8          CD,  1pin
  [ Button SW port ] 
         SW  :PD2(INT0),  4pin, D2, Active low
* Download arduino_wave_player_lite_atmega328p_v1.3-201604.zip v1.3: (1) FF/Rewindがリファクタでバグってしまっていたのを修正。orz (2) バージョン表示を追加。 (3) 再生中の曲の最初に戻る[F]キーを追加。 v1.2: 最初の版 arduino_wave_player_lite_atmega328p-v1.2-201603.zip 書き込み方: 解凍して出てきた arduino_wave_player_lite_atmega328p_38400bps.hex というファイルをこのツール http://mpu.seesaa.net/article/399685603.html にドラッグ・ドロップして 書き込みます。 * 動作確認 /musicフォルダにWAVファイル(fs=32KHz以上推奨(注2))を入れたSDカードを差し込んで 電源を入れると,基板上のLED(TX)がチカチカします。 十秒以内くらいでこのチカチカが停止すれば,既に音楽再生が開始されています。 TeraTermを38400bpsの設定で開けば操作可能です。 圧電素子や100円スピーカをつなげば音声確認できるかと思います。(こちらでは未確認) * avr-gccのバージョン arduino-1.6.8に付属の gcc version 4.8.1 (GCC) を使用。 これより前の版は使わない方がよい。 後の版なら大丈夫と思われるが,あまりチェックしていない。 というか,大勢のユーザが使用しているarduino版がひとまず安心。 * Petit(ぷち) FatFs コンパイル・オプションでPetit・FatFs(以下 PFatFs)を使ってコンパイルできます。 動作はコンパチブル。 問題: 音が「ブヨブヨ」でちょっと使えません。 :D バッファーアンダーフローの対策がなければ,「ブチブチ。。。」という感じに なります。 原因: 最初期から変わっていない気がする。 FatFsよりもSDカードの読み込み速度が遅いと思って上記の「SDカード速度計測機能」で 比較するとほとんど同じ値を出していた。 フラグメント問題かもしれないが詳細未調査。 * その他のWave player TMRpcm Arduinoのスケッチタイプの以下のWAV・PWMプレイヤーがある様です。 標準でfs:32KHz mono。 拡張でもう少しアップするみたいだけど詳細不明。 TMRpcm https://github.com/TMRh20/TMRpcm/wiki Youtube動画 https://www.youtube.com/watch?v=LbqPgJe3Qd4 TMRpcm/Arduinoのフォーラム https://forum.arduino.cc/index.php?topic=179027.0 SimpleSDAudio これもスケッチタイプ http://www.hackerspace-ffm.de/wiki/index.php?title=SimpleSDAudio * 参考 Arduinoシリーズ15種類の違い | まとめ比較表 http://ideahack.me/article/134 (注1) いろいろやればできそうなんだけど,この手の機能はキリがないので Lite版仕様ということにしました。今のところ。 (注2) サンプリング周波数(fs)が低すぎる場合,ちゃんとしたフィルタを入れないと PWMノイズと折り返しノイズ、(キーーン!)で耳が痛いです。xD
posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | PCM/WAVE | このブログの読者になる | 更新情報をチェックする

2016年01月12日

WAVE/PCM再生: mbed: NUCLEO-F030R8で10bit PWM音楽再生

WAVE/PCM再生: mbed: NUCLEO-F030R8で10bit PWM音楽再生
wave_player_pwm_10bit_nucleo-f030r8-frizing.gif
* はじまり
    mbed NUCLEO-F030R8を買った。
    これには12bitのDACがついてないので、いつもの様にシンプルPWMで
    PCM/WAVEファイルを再生してみた。
    PWMの周期タイマに最大48MHz入力可能なのでfs(サンプリング周波数)=44.1KHzの時,
    48MHz動作のNUCLEO-F030R8だと音楽の解像度は10ビットになります。

    必要なものは以下の動画の様にSDカード、抵抗とコンデンサ少々という、
    部品箱にありそうな部品だけでできちゃいます。(^^)/

* 今回のポイント
    諸般の経緯によりuVision4を使った32KB制限の下で作ることになってしまったのだった。orz
    STM32マイコンは下層ドライバ(STM32Cube)のオーバーヘッドが大きい。
    従って操作仕様は一度全部消去して新たにシンプルなものに作り替え,
    Lite版仕様とした。
簡略化(Lite)仕様:
    (1) リセット直後 /music フォルダ内の*.wavファイルを順に再生し,
        全て再生し終わったら最初から繰り返すという動作。
    (2) 再生中はポーズ/ポーズ解除のみ可能。('p','s'キー)
    (3) 次の曲に飛ばすことは可能。('n',Spaceキー)
    (4) 前の曲に戻ったり,任意の曲の選択機能はない。
    (5) 全曲のリストアップ機能もない。
        これをやると曲を選択したくなるのでグッと我慢する。:D
新機能:
    (1) 32ステップ・デジタルボリュームを搭載。
        割り算・かけ算なので何ステップでもいいんだけど...
    (2) 可変速再生を「'u'」(アップ),「'd'」(ダウン)キーに割り当てて操作性を向上。
    (3) LEDによる再生中のイジケータを追加。(かなりいいかげんで不正確なものの動作確認にはなる :-)
    (4) 再生時間インジケータ。
        最初にトータル時間を水平ライン(----+--等)で表示し,再生中はその下に
        10秒ごとの経過ライン(***)を表示していく。
その他:
    uVision4のローカルコンパイル環境で,
    最適化オプション「-O1」でデバッグ可能なコードサイズ(32KB以下)とした。
    但し,以下のコードサイズ最小化のワザを適用している。
    mbed のバイナリサイズを減らす方法 
    https://developer.mbed.org/users/MACRUM/notebook/howto-reduce-binary-size/

* mbed使用ライブラリ
    一部のmbedライブラリを少し改造してあります。
SDFileSystem:
    Offical版SDFileSytemをDMA化したものを使用。
    mbed: SDFileSystemのDMA化 Nucleo-F030R8編 2016
FastPWM:
    https://developer.mbed.org/users/Sissors/code/FastPWM/

* 10bit PWMの再生音: NUCLEO-F030R8 
    以下の動画は、実際にNUCLEO-F030R8で再生した音をパソコンの録音入力に入れて
    作ったものです。
    再生した音楽データ(WAVE/PCM)は、foobar2000でWAV変換した16bit/Stereo/44.1kHzのものです。

    1曲目:Music: Serenity
    前回のF411REで2番目に掲載したアコースティック・ギター系の曲が
    なぜか好評だったので,だったら最初に置いてみた。 :D
    

    2曲目:Music: About That Oldie 
    今や破竹の勢いのメーガン・トレイナーの特大ヒット曲を彷彿(ほうふつ)させる。曲名もアレだし。
    キーワード:1960s'のドゥーワップ。
    

    3曲目:Music: Gemini Robot
    

* 機能
    ここまでの機能メモ。
    UARTターミナルベース(115200bps)。
    
WAVEファイル:
    foobar2000で*.WAVファイルに変換したWAVEファイルをベースとする。それ以外は未チェック。
    WAVEファイルは、サンプリング周波数48kHzまでの任意の周波数を受け付ける。
    WAVEファイルヘッダに書いてある周波数で再生する。
    動作確認は、fs=32kHz,44.1kHz,48kHz。
    データ長は、16bit/8bit
    Stereo/mono

操作仕様:
    「Operation」
    ここを参照

* 出力のローパスフィルタ
    出力のフィルタは以下の2種類を考えてみた。
    動画の中のものは出力の減衰が多くフィルタ効果もほとんどないので実際は以下の感じか。
    但し,所詮一次のローパスフィルタなので特性は気休め程度。:D
             Low pass filter    C2
PWM out >----/|/|/|----+---------||--------> Audio in
               R1      |        +
                       |
                      ===  C1
                       |
                     ////

        C2 = 2.2uF ~ 10uF
Pattern1: 
        R1 = 3.3K Ohm
        C1 = 1500pF ~ 2200pF
Pattern2: 
        R1 = 680 Ohm
        C1 = 0.01uF
* SDカード接続図
/* SD card pin
                                           NUCLEO-F411       NUCLEO-F030R8
Pin side
--------------\
        9  ==== \    DAT2/NC
            1 ===|   CS/DAT3    [CS]         D10 / PB_6        D10 / PB_6 
            2 ===|   CMD/DI     [DI]         D11 / PA_7        D4 / PB_5
            3 ===|   VSS1       [GND]        GND               GND
Bottom      4 ===|   VDD        [3.3V]       3.3V              3.3V
View        5 ===|   CLK        [CLK]        D13 / PA_5        D3 / PB_3
            6 ===|   VSS2       [GND]        GND               GND
            7 ===|   DO/DAT0    [DO]         D12 / PA_6        D5 / PB_4
            8 ===|   DAT1/IRQ
-----------------

                                           NUCLEO-F411       NUCLEO-F030R8
Logo side
-----------------
            8 ===|   DAT1/IRQ
            7 ===|   DO/DAT0    [DO]         D12 / PA_6         D5 / PB_4
            6 ===|   VSS2       [GND]        GND                GND
Top         5 ===|   CLK        [CLK]        D13 / PA_5         D3 / PB_3
View        4 ===|   VDD        [3.3V]       3.3V               3.3V
            3 ===|   VSS1       [GND]        GND                GND
            2 ===|   CMD/DI     [DI]         D11 / PA_7         D4 / PB_5
            1 ===|   CS/DAT3    [CS]         D10 / PB_6         D10 / PB_6 
        9  ==== /    DAT2/NC
--------------/
*/
* NucleoのFrizingボードデータ 以下のボード図がFrizingに標準装備されているので便利かも。 Frizing上で"nucleo"で検索すると出てくる。 mbed-stm32-nucleo-board.gif * ハマりポイント xD uVision5で使えない orz:STM32F0シリーズはuVision5ならFlash 256KBまで無料」というのを使おうと思ったら, なんと家の環境(Windows10)では,エクスポートしたmbedプロジェクトをオープンできない という状況に陥った。orz オープンした途端にuVision5がクラッシュするのだった。 orz orz これが原因で32KB縛りのuVision4を使うことになったのだった。 (今回はGCCを使っていない) 内蔵クロック(HSI)の初期補正値がむちゃくちゃだった orz: 当初,音楽再生速度が遅いのでソフトがどこかおかしいかと思っていたが, 結局,リセット直後のレジスタ初期値がデータシートと全然違う値になっていて HSIクロックが5%も遅かったのだ。orz orz orz マイコンそのもののバグなのは間違いない。 (デバッガでレジスタ見たから)
 __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST( RCC_HSICALIBRATION_DEFAULT );
をmain()の最初に追加することで解決した。orz これは単にレジスタの初期値をデータシート通りにしただけだ。 PLLで48MHzにした後の周波数誤差は0.3%だった。(^^)/ * リベンジ的な要素 以前LPC1114(Cortex-M0)で作った再生動画が著作権侵害でクレームがついて,YouTubeから削除した 経緯がある。 Cortex-M0でWAVE/PCM再生の再挑戦でもあるのだった。
posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | PCM/WAVE | このブログの読者になる | 更新情報をチェックする

2015年01月04日

PCM/WAVE: dsPIC33FJ64GP802の16bit DACでWAVE再生 2015

PCM/WAVE: dsPIC33FJ64GP802の16bit DACでWAVE再生 2015

* はじまり
* DAC出力は非常に簡単だった。
* ソフト
* ハード
* オペアンプは1個で作る
* サンプリング周波数問題
* 水晶発振子問題
* 内蔵発振器だけで、fs=44.1KHzと48KHzを再生可能にする
    オーバークロック:
* FOSC: PLLとDAC周波数設定
    オーバークロックしない版:
    オーバークロック版:
* fs依存でFOSCを切り換える
* Config設定値
* DAC出力の差動合成とオペアンプの電源電圧
    オペアンプ電源 3.3Vの場合:
    最悪値:
    オペアンプ電源 5Vの場合:
    最悪値:
    結論:
* 2つの水晶発振子でfs=44,1KHzと48KHzを切り換える一つの方法
* 中点電位の低インピーダンス化
* 音質はどう?
* オペアンプなしでひとまず音を出す
* 8MHzの水晶発振子で音を出す (^^)/ fs=44.1KHz, 48KHz対応


dspic33fj64gp802-16bit-dac-wave-player.jpg
* はじまり
dsPIC33FJ64GP802というマイコンがあって、
http://akizukidenshi.com/catalog/g/gI-08458/
480円(税込)だった。
実はこのマイコン、オーディオ専用の16bitDACを積んでいるんです。
(1) DAC部:
    256倍オーバーサンプリングDAC搭載。
    差動電圧出力。 1.15Vpp (中点電位1.65V)
    fs=100KHz まで可能。
(2) MCUは40MIPSで動く。
(3) DMAもある。
(4) 他にも盛りだくさん。:D
と、なかなか良い感じ。
年末に購入しておいたのでこの機会にChaNさんのFatFsを使ってSDカードから、
WAVE/PCMの音楽データを再生してみました。

参考:
(1) 後閑さんが本をだしている様です。(未購入)xD
(2)  「フルート吹きのMIDI工房」さんのページ
        ● 実験テーマ57
        http://www7b.biglobe.ne.jp/~nobosan_flute/lab_theme57.htm

* DAC出力は非常に簡単だった。
configとクロック周りの設定をしたら、データシートのDAC設定通りに設定すれば、
あっという間にDACから信号が出ちゃいました。
実質、DAC割込みを始動させるだけで動きます。

PWMとかタイマー設定とか無関係です。
PWMで音出す方がよっぽど手間がかかります。:D

* ソフト
PIC24FとdsPIC33Fは基本的な部分は結構同じなので、
(イヤ、微妙に違うと言えば違うんだけど。。。オイ)
以前、PIC24FでPWM再生した時のソフトで、PWMの周期割込みをDAC割込みに
変えるだけでOKでした。 楽ちんだった。(^^)/
PIC24F: 8bit PWMの音 / PCM/WAVE再生
SPI:
    PIC24FJ64GA002はDMAがないせいか、SPIに8段のFIFOがあって(^^)/だったけど、
    dsPIC33FはDMAがあるせいで、SPIに多段FIFO積んでない orz。
    なくても大丈夫だったけど。オイ
* ハード
ひとまずブレッドボードを使って部品箱にある様な部品だけで音だし実験してみたい
という方針。

* オペアンプは1個で作る
http://ww1.microchip.com/downloads/en/DeviceDoc/21685d.pdf
差動合成用のオペアンプは、後閑さんの作品だとMCP6022を2個使いだけど、
(MCP6022はオペアンプ2個入りなので1個でできます)
そんなオペアンプ部品箱にないっ!
ブレッドボードだとスペースもないので、2回路入りで単電源で、3V〜5Vの
「レールtoレール」とか 「フルスイング」と 言われる
部品箱にある以下の品種を使ってみた。
LM358N   @20円  3V〜32V   SR=0.5V/u   http://akizukidenshi.com/download/LM358N_NS.pdfs
LMC662   @80円  5V〜15V   SR= 1.1V/us http://www.tij.co.jp/jp/lit/ds/jajsbe5/jajsbe5.pdf
OPA2340  @?    2.7V〜5V   SR= 6V/us   http://www.ti.com/lit/ds/symlink/opa340.pdf
OPA2350  @?    2.7V〜5.5V SR= 22V/us  http://www.ti.com/lit/ds/symlink/opa350.pdf

オペアンプは最終的に5V駆動にして使える品種を増やした。(^^)/
後述。

* サンプリング周波数問題
別に問題というほどではないけど、後閑さんの作品だとサンプリング周波数(fs)は
44.1KHzに固定なのです。
べつに固定でもいいんだけど、何とかfs=48KHzのWAVEファイルも再生したいのだった。

* 水晶発振子問題
別に問題じゃ。。。オイ
fs=44.1KHzと48KHzのWAVEファイルを再生しようとすると、外部に二つの水晶発振子を付けて切り換える
様なハードが必要で、ちょっとめんどくさい。:D
そもそも部品箱に「11.2896MHz」や「12.288MHz」とかの水晶発振子はないのだった。xD
ということで、
精度(誤差)が2%のマイコン内蔵発振器でなんとかならないか考えたのが以下のメモ。
内蔵発振は2%の精度だけど、最大誤差が2%なので実際はもっといいはず。
実測してみると大体0.2%だった。(^^)/ (安定度は今ひとつだけど)

これ売ってない。 orz AK8138MV
http://www.akm.com/akm/jp/product/datasheet1/?partno=AK8138MV
大げさ過ぎる気もする。:D

* 内蔵発振器だけで、fs=44.1KHzと48KHzを再生可能にする
そこで表計算ソフトでいろいろ探ってみると多少の周波数誤差はあるものの、
内蔵発振器7.3728MHzを元にfs=44.1KHzと48KHzのWAVEファイルを再生できることが分った (^^)/
オーバークロック:
    丁度いい周波数がFOSCをオーバークロックしたものと、ちょっとFOSCが小さめの時と
    2種類あった。FOSCが小さいとちょっともったいないので
    オーバークロック版で最初は試した。
DACへはFOSCクロックを供給します。

* FOSC: PLLとDAC周波数設定
細かいことは表計算ソフトに任せて :D 結果だけメモしておきます。
もっといい組合わせがあるかもしれませんが現時点では不明です。
オーバークロックしない版:
        FRC = 7.3728MHz (内蔵クロック)
        FRCDIV:
            分周比 = 1/1  設定値=0  
            FRCDIV後出力周波数: 7.3721MHz
        PLLPRE:
            分周比 = 1/3  設定値=1
            PLLPRE後出力周波数: 2.4576MHz
        APSTSCLR:
            分周比 = 1/8 設定値=4
    fs=44.1KHz:
        M (PLL multiple) = 37
        PLLDIV: 設定値 = 35
        PLLPOST:
            分周比 = 1/2 設定値=0
            PLLPOST後出力周波数: 45.4656MHz (=FOSC)
        fsに対する誤差: -0.6757%
        FOSC = 45.4656MHz  
        FCY  = 22.7328MHz
        MCU処理能力 約23MIPS
    fs=48KHz:
        M (PLL multiple) = 40
        PLLDIV: 設定値 = 38
        PLLPOST:
            分周比 = 1/2 設定値=0
            PLLPOST後出力周波数: 49.1520MHz (=FOSC)
        fsに対する誤差: 0%
        FOSC = 49.1520MHz  
        FCY  = 24.5760MHz
        MCU処理能力 約25MIPS

オーバークロック版:
        FRC = 7.3728MHz (内蔵クロック)
        FRCDIV:
            分周比 = 1/1  設定値=0  
            FRCDIV後出力周波数: 7.3721MHz
        PLLPRE:
            分周比 = 1/2  設定値=0
            PLLPRE後出力周波数: 3.6864MHz
        APSTSCLR:
            分周比 = 1/16 設定値=3
    fs=44.1KHz:
        M (PLL multiple) = 49
        PLLDIV: 設定値 = 47
        PLLPOST:
            分周比 = 1/2 設定値=0
            PLLPOST後出力周波数: 90.3168MHz (=FOSC)
        fsに対する誤差: 0%
        FOSC = 90.3168MHz  
        FCY  = 45.1584MHz
        MCU処理能力 約45MIPS
    fs=48KHz:
        M (PLL multiple) = 53
        PLLDIV: 設定値 = 51
        PLLPOST:
            分周比 = 1/2 設定値=0
            PLLPOST後出力周波数: 97.6896MHz (=FOSC)
        fsに対する誤差: 0.6289%
        FOSC = 97.6896MHz  
        FCY  = 48.8448MHz
        MCU処理能力 約49MIPS

49MIPS !! xD
って オイ

* fs依存でFOSCを切り換える
再生するWAVEファイルのfsによって、PLLやDACクロックの設定を
上記の値に切り換えます。
FOSCはマイコンシステムの基本クロックなので、関連する周辺I/OでFOSC依存なものは、
クロックの再計算が必要です。
といっても今のところ、Timer,UARTとSPI,FatFsくらい。
今のところ、usecオーダの「delay()ベタ待ち系」は放置してあります。:D
これで、
通常再生時にfsを自動切り替えできるので、かなりうれしい感じになりました。(^^)/

* Config設定値
PICの場合、これをちゃんと書かないとうまく動かないのだ。
下で出てくる8MHz水晶発振子の設定も入っています。
#include "sys.h"
_FBS(     BWRP_WRPROTECT_OFF
        & BSS_NO_BOOT_CODE
        & RBS_NO_BOOT_RAM);

_FSS(   SWRP_WRPROTECT_OFF
        & SSS_NO_SEC_CODE
        & RSS_NO_SEC_RAM);

_FGS(   GWRP_OFF & GSS_OFF );
_FWDT( FWDTEN_OFF);
_FPOR( FPWRT_PWR2);
_FICD( ICS_PGD1 & JTAGEN_OFF );

#ifdef IRC_7_3728MHZ
_FOSCSEL( FNOSC_FRCPLL &IESO_ON );
_FOSC(   POSCMD_NONE
        & OSCIOFNC_OFF 
        & IOL1WAY_OFF
        & FCKSM_CSDCMD);

#elif defined(EXT_OSC_8MHZ)
_FOSCSEL( FNOSC_PRIPLL &IESO_ON );
_FOSC(   POSCMD_HS
        & OSCIOFNC_ON 
        & IOL1WAY_OFF
        & FCKSM_CSDCMD);
#else
#error
#endif
* DAC出力の差動合成とオペアンプの電源電圧 差動合成前のマイコンの出力Lch(左チャンネル)の場合、 DAC1LP = (+)1.15Vpp DAC1LN = (-)1.15Vpp ( Typ. 1.15Vpp = VDACH - VDACL, Max 2Vpp オイ) これを外部オペアンプ(以下オペアンプ)を通して差動合成すると、 DAC1L = (+)1.15Vpp - (-)1.15Vpp = 2.3Vpp の信号となる。 (= ±1.15Vp) オペアンプ電源 3.3Vの場合: Vcc/2=1.65V を中点電圧とするので、オペアンプ出力振幅の最大(max)、最小値(min)は、 Vout = 1.65V ±1.15Vp = 0.5V (min) 〜 2.8V (max) となる。 最悪値: DAC部のバラツキが最大値だった場合、 Vout = 1.65V ±2.0Vp = -0.35V (min) 〜 3.65V (max) となり、3.3V電源では破綻する。 音が悪い感じに聞こえる。 オペアンプ電源 5Vの場合: Vcc/2=2.5V を中点電圧とするので、オペアンプ出力振幅の最大、最小値は、 Vout = 2.5V ±1.15Vp = 1.35V (min) 〜 3.65V (max) となる。 最悪値: バラツキの最大値だった場合、 Vout = 2.5V ±2.0Vp = 0.5V (min) 〜 4.5V (max) となり、5V電源なら全く問題ない。 結論: オペアンプの電源を5Vにした方がより良いのと、使えるオペアンプの種類も増えるので 可能なら5Vが良いのだ。 もし音が変な場合は、DAC出力の値が上に書いた様に「ハズれな物に当たった :D 」可能性もあるので、 オペアンプの電源を5Vにしてみるのも一つの手かも。 * 2つの水晶発振子でfs=44,1KHzと48KHzを切り換える一つの方法 多少の誤差を許容すればDACにクロックを供給する方法は結構たくさんある。 上の方法で内蔵クロックを使った部分を「例えば8MHzの水晶発振子」にすれば同様に多少のfs誤差で 2種類のfsを切り換える事は可能だ。 でもやっぱり、 fsの誤差0ゼロで使いたいといった場合、 方法(1): (a) プライマリクロック端子(OSC1/OSC2)に12.2880MHzの水晶発振子を付ける。 (諸設定値は変える必要あり) (b) DAC用のAuxiliary OSCとして(SOSCO/SOSCI)端子に11.2896MHzの水晶発振子を付ける。 fs=48KHzはFOSCを分周した物を使い、fs=44.1KHzはそのまま11.2896MHzを使えば、 誤差ゼロシステムとなる。 メリット: (i) システムクロックを固定化できる。 (ii) 水晶発振子を2つ付けるだけなので回路が簡単。 デメリット (i) I/Oピンを水晶発振子で4つも使ってしまう。 * 中点電位の低インピーダンス化 オペアンプの中点電位の絶対値については、そんなに意味はなくて、(なくはないんだけど :D) 上に書いた様にレールtoレールの上限、下限値からある程度の余裕が確保できるポイントに設定できれば良い。 それよりも、中点電位の変動を少なくする方が重要と考える。 従って、中点電位生成にボルテージフォロア等を使った方が良いし、 当然、オペアンプの電源は定電圧化し、微動だにしない様にしておくのが良い。 * 音質はどう? そもそもブレッドボードなので、xD xD なんだけど、 さらに、内蔵クロックベースだからさらに、 xD なんだけど、 そういう話を知らないで聴けばけっこういい音だと思います。 十分合格圏だと思います。 オペアンプは、泣く子も黙る :D バーブラウンのOPA2350を5V駆動、出力のカップリングコンデンサは3.3uFのフィルムコンデンサ です。 ここに電解コンデンサを使うのは断固拒否した方がいいと思います。xD LME49721MAというオペアンプも結構良いらしいのでそのうち聴いてみる。 * オペアンプなしでひとまず音を出す 「部品箱に単電源用のオペアンプなんてないっ!」 って言う場合。 xD とりあえず、 DAC1LP とDAC1RP端子に2.2uF〜10uFのコンデンサ(電解可 xD)をつなげて、 その先をGNDとあわせてヘッドホンアンプやPCの入力端子に入れれば実験的な音は出る。 試してないけど。:D * 8MHzの水晶発振子で音を出す (^^)/ fs=44.1KHz, 48KHz対応 8MHzの水晶発振子なら部品箱にあるので、これで音だししてみた。 (^^)/ やっぱり、こっちのほうがいい音します。:D 水晶の精度は必須だ。xD ブレッドボードでよくここまで出るね。 合格 ! (ただ、よく聴くと電源に起因すると思われる微小ノイズがわかる) クロック設定: オーバークロックしない版: FRC = 8.0000MHz (水晶発振子) FRCDIV: 分周比 = 1/1 設定値=0 FRCDIV後出力周波数: 8.0000MHz PLLPRE: 分周比 = 1/3 設定値=1 PLLPRE後出力周波数: 2.6667MHz APSTSCLR: 分周比 = 1/8 設定値=4 fs=44.1KHz: M (PLL multiple) = 34 PLLDIV: 設定値 = 32 PLLPOST: 分周比 = 1/2 設定値=0 PLLPOST後出力周波数: 45.3333 (=FOSC) fsに対する誤差: -0.3859% FOSC = 45.3333MHz FCY = 22.6667MHz MCU処理能力 約23MIPS fs=48KHz: M (PLL multiple) = 37 PLLDIV: 設定値 = 35 PLLPOST: 分周比 = 1/2 設定値=0 PLLPOST後出力周波数: 49.3333 (=FOSC) fsに対する誤差: -0.3676% FOSC = 49.3333MHz FCY = 24.6667MHz MCU処理能力 約25MIPS * 追記 (2016/01) 実は書き忘れていたことがありました。 DACのクロックは上述の様に設定すると 再生速度が2倍速くなってしまいました。 従ってDACモジュール内の分周器で適当に1/2してつじつまを合わせています。 何度も見直しましたが, 多分データシートがどこか間違っているんじゃないかと思います。 自分の勘違いも否定しませんが,最終的につじつまを合わせて 正しく再生できたのでそこで終了としました。
posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | PCM/WAVE | このブログの読者になる | 更新情報をチェックする

2014年11月09日

WAVE/PCM再生: mbed: NUCLEO-F411RE で11bit PWM音楽再生

WAVE/PCM再生: mbed: NUCLEO-F411RE で11bit PWM音楽再生
だいぶ前に、mbed NUCLEO-F411REを買った。
これには12bitのDACがついてないので、いつもの様にシンプルPWMで
PCM/WAVEファイルを再生させてみた。
音楽の解像度は周期タイマに100MHz使えるので11ビットになります。
84MHz動作のNUCLEO-F401REだと10ビット解像度になります。(持ってないけど)

必要なものは以下の動画の様にSDカード、抵抗とコンデンサ少々という、
部品箱にありそうな部品だけでできちゃいます。(^^)/
(注)
動画が微妙に音飛びしますが、録音ソフトの調子が今ひとつなせいだと思われます。
直接音は大丈夫でした。

* mbed使用ライブラリ
一部のmbedライブラリを少し改造してあります。
SDFileSystem:
    以下の「本家版じゃない改良版」をほんの少し改造しました。
    http://developer.mbed.org/users/neilt6/code/SDFileSystem
    本家版に比べて速度がアップしているという事です。
    このライブラリはSDHCカードしか認識しませんでした。orz
FastPWM:
    http://developer.mbed.org/users/Sissors/code/FastPWM/
    これは便利。高分解能版です。
    1クロック単位の設定が可能です。(^^)/
    現在は以下のmbedだけに対応しています。
    LPC1768, 
    LPC11u24, 
    KLxxZ, 
    K20D50M, 
    F030R8, 
    F401RE,
    F411RE
    mbed標準のPWMでは、周期(とduty?)の最小分解能が1usecしかなくて、
    fs=44.1KHz(22.68usec)に対する誤差が大きくなってしまいます。
    5分の曲が4秒くらい長く再生される。
   (といっても、その違いが分るかどうかは別 :D )
millis:
    これも便利。arduino風。
割込み:
    PWMの周期に同期した割込みが欲しかったのでSTM32のHALドライバを使っちゃいました。
    非同期ならTickerでいけるかも。今後試してみる予定。
    非同期はx
    周期割り込みをTickerクラスにして、非同期型にしてみた。
    予想通りノイズがひどくてボツでした。
    PWMのduty設定と位相がどんどんズレていって、遅延が最大になったところで同じデータが2度送られて
    ノイズになると思われます。
        EXTIもorz
        PWMの立ち上がりエッジをEXTIポートに入れて割込みを作ってやってみた(同期式)けど、orzだった。
        原因は深追いしてません。:-)


* 11bit PWMの再生音
以下の動画は、実際にNUCLEO-F411REで再生した音をパソコンの録音入力に入れて
作ったものです。
再生した音楽データ(WAVE/PCM)は、foobar2000でWAV変換した16bit/Stereo/44.1kHz or 48kHzのものです。

1曲目: fs=44.1kHzデータ


2曲目: fs=44.1kHzデータ


3曲目: fs=48kHzデータ
PC取り込み時に44.1kHzにリサンプリングされちゃいました。orz


* PWMクロック周波数と音声解像度の関係
pwm-clock-vs-resolution.png


* SDFileSystemの速度
上で使ったSDFileSystemライブラリの速度を計測してみた。
CrystalMark値:
まずは、PC上のCrystalMarkを使ってシーケンシャルリードの速度を計測した。
SDカードはClass4(@4)と不明な物(@?)がある。
    メーカ
    Good-J      16G FAT32 SDHC @10: seq read: 19.5MB/s , write: 12.3MB/s
    Victor       4G FAT32 SDHC  @4: seq read: 17.8MB/s , write: 11.3MB/s
    BUFFALO     16G FAT32 SDHC  @4: seq read: 17.8MB/s , write:  4.3MB/s
    Sony         8G FAT32 SDHC  @4: seq read: 16.2MB/s , write:  4.7MB/s
    IO DATA      1G FAT   SD    @?: seq read: 11.9MB/s , write:  2.4MB/s
    Transcend    2G       SD    @?: seq read:  9.9MB/s , write:  5.3MB/s
    Sony         4G FAT   SDHC  @4: seq read:  5.4MB/s , write:  4.9MB/s
以下は、SDFileSystemライブラリ用のベンチマークソフト結果。 SDFileSystem: NUCLEO-F411RE SysClock=100MHz 読出しバッファサイズは512バイト、SPIクロックは12MHzとした。
     Good-J   16G FAT32 SDHC @10: SPI SCLK 12MHz: buf=512byte read: 510KB/s write: 81KB/s 
     Victor    4G FAT32 SDHC  @4: SPI SCLK 12MHz: buf=512byte read: 507KB/s write: 46KB/s 
     Sony      4G FAT   SDHC  @4: SPI SCLK 12MHz: buf=512byte read: 462KB/s write: 21KB/s 
     BUFFALO  16G FAT32 SDHC  @4: SPI SCLK 12MHz: buf=512byte read: 456KB/s write: 87KB/s 
     Sony      8G FAT32 SDHC  @4: SPI SCLK 12MHz: buf=512byte read: 302KB/s write: 19KB/s 
容量2Gバイト以下のSDカードは読み書きできませんでした。 orz orz 結果: 速度改良版だけあってSPIクロック12MHzなら一部のカードを除いて十分使える。 (今回の用途なら) ただし、マイコンのクロックが100MHzと高速なのも一因。 試しに48MHzのSTM32F0-Discoveryだと最高でも「200KB/s」止まりだった。orz NUCLEO-F411REでSPIクロック25MHzにしたら「700KB/s over」くらい出ていた。(Victorのカード) * 機能 ここまでの機能メモ。 UARTターミナルベース(115200bps)。 WAVEファイル: foobar2000で*.WAVファイルに変換したWAVEファイルをベースとする。それ以外は未チェック。 WAVEファイルは、サンプリング周波数48kHzまでの任意の周波数を受け付ける。 WAVEファイルヘッダに書いてある周波数で再生する。 動作確認は、fs=32kHz,44.1kHz,48kHz。 データ長は、16bit/8bit Stereo/mono 操作仕様: 起動画面:
*** PCM/Wave Player mode ***
<WAVE> "*.WAV"

[  0]       CALL.WAV [  1]      ELGAR.WAV [  2]   EMPTYHRT.WAV
[  3]   ILOVEYOU.WAV [  4]      ETUDE.WAV [  5]     HOTELC.WAV
[  6]      ASCOT.WAV [  7]       HERO.WAV [  8]        AK1.WAV
[  9]        AME.WAV [ 10]      ARTP1.WAV [ 11]      ARTP7.WAV
[ 12]   AVEMARIA.WAV [ 13]   BETTERIN.WAV [ 14]   BIRTHDAY.WAV
Enter:[L]ist, [P]lay/Pause, [S]top, [C]:Play all, [I]nfo, [Q]uit
9
  [PCM]      AME.WAV 44100Hz 16Bit Stereo 11689984 Byte
>>>>>>
     Real 01:06, Logical 01:06 Sec.  End music.
6
  [PCM]    ASCOT.WAV 44100Hz 16Bit Stereo 46206908 Byte
>>>>>> >>>>>> >>>>>> >>>>>> >>
     Real 04:22, Logical 04:22 Sec.  End music.
曲、 フォルダ選択 1.Enterキーか「l(エル)」キーを押してファイルリストを出します。 2.曲番号を入力し、Enterキーを押すと再生します。 3.フォルダ番号を選択すると、そのフォルダ内容をリストアップします。 以降の操作(再生、ポーズ等)はそのフォルダの曲に対して作用します。 ['b'], [ESC]: ルートフォルダに戻ります。ルートのファイル一覧を表示します。 動作モード表示 [C] : フォルダ内の全曲ループ再生モード中。 [R] : 1曲リピート再生モード中。 [E] : 高速・スロー再生モード中。 例:[CE]なら、高速・スロー再生で、全曲ループ再生する状態。
キー動作 再生中 停止中 ポーズ中
0 - 9 曲、フォルダ番号選択 -o-
b, ESCルートフォルダに戻る -o-
b, ESC再生停止 o-o
l(エル), Enter ファイル一覧表示。 -oo
p ポーズと再開。 PausePlayPlay
q プレーヤモードを終了。 ooo
r 再生中の曲を連続リピート設定。 ooo
s 再生停止。 o-o
.(ピリオド), >, Space 次の曲。o o o
,(カンマ), < 前の曲。 ooo
[ 再生中の曲の先頭から再生。 ooo
c全曲ループ再生とその解除。(フォルダは含まず) ooo
1〜44段階スロー再生。再生中に押す。'0'で解除。 o-o
5〜73段階高速再生。再生中に押す。'0'で解除。 o-o
hヘルプ -oo
* ハマりポイント xD
posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | PCM/WAVE | このブログの読者になる | 更新情報をチェックする