Leonardo で SDカードの WAVファイルを再生する [Arduino]
Leonardo で SDカードの読み取りができるのなら、そこから WAVファイルの再生にもいけるだろう、、ということでやってみました。
Leonardo で使われている ATmega32u4 には、ATmega328P にあった 8bit Timer/Counter2 がないので以前のスケッチを少し書き換えました。
少し書き換えただけですが、また新たな勉強でした。
16bit の Timer/Counter1 を 8ビットで使うことにしました。
以前のスケッチは、タイマーがオーバーフローするのを割り込みにしていましたが、16ビットになりオーバーフローでの割り込みではだめなので、input capture register1 (ICR1) で Timer/Counter1 のTOP値を8ビットの0xFF (255) として、タイマ/カウンタ1 捕獲割り込みというもので割り込むようにしてみました。
OC1Aを使用しましたが、このピンは Uno (PB1) でも Leonardo (PB5) でも共に Arduino上はデジタル9番なので両機種に対応できているはずです。
せっかくなので、ダ・ヴィンチ32U を使ってみました。
写真の圧電サウンダでは音量が足りませんでしたが、100円ショップスピーカを直結(たぶん良くない)したところそこそこの音量が得られました。
Leonardo で使われている ATmega32u4 には、ATmega328P にあった 8bit Timer/Counter2 がないので以前のスケッチを少し書き換えました。
少し書き換えただけですが、また新たな勉強でした。
16bit の Timer/Counter1 を 8ビットで使うことにしました。
以前のスケッチは、タイマーがオーバーフローするのを割り込みにしていましたが、16ビットになりオーバーフローでの割り込みではだめなので、input capture register1 (ICR1) で Timer/Counter1 のTOP値を8ビットの0xFF (255) として、タイマ/カウンタ1 捕獲割り込みというもので割り込むようにしてみました。
OC1Aを使用しましたが、このピンは Uno (PB1) でも Leonardo (PB5) でも共に Arduino上はデジタル9番なので両機種に対応できているはずです。
// 「SDカードのWAVファイルを再生」
// 16MHzのArduino で 256 clock毎に割り込むので 62.5kHz(8bit Monoral)が理想だが
// ボクの持っているソフトが対応していないので、32kHz(8bit Stereo)で代用
// Leonardo対応バージョン
#include <SD.h>
#define BUF_SIZE 384 // バッファ・サイズ
volatile uint8_t // グローバル変数
buf[2][BUF_SIZE], // バッファ
buf_page, // バッファ・ページ
buf_flg; // バッファ読み込みフラグ
volatile uint16_t buf_index; // バッファ位置
volatile uint16_t read_size[2]; // バッファ読み込みサイズ
void setup() {
pinMode( 4, OUTPUT); // SDライブラリ使用時のお約束 (CSピンの指定)
while( !SD.begin(4) ); // ライブラリとSDカードを初期化
// PWM初期化
pinMode( 9, OUTPUT); // OC1A使用 - Uno(PB1), Leonardo(PB5)ともにD9
TCCR1A = _BV(COM1A1) | _BV(WGM11); // 高速PWM (OC1A 非反転)(TOP値:ICR1), 分周なし
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // (COM1A1-0=10, WGM13-0=1110, CS12-0=001)
ICR1 = 0xFF; // input capture register:TOP値を255(8bit)とする
}
void loop() {
File dataFile;
if ( !(dataFile = SD.open( "hoge.wav" )) ) return; // error opening wavefile
buf_index = 44; buf_page = 0; buf_flg = 1; // パラメータ設定 (44byteはヘッダ)
read_size[buf_page] = dataFile.read( (uint8_t*)buf[buf_page], BUF_SIZE );
TIMSK1 |= _BV(ICIE1); // Input Capture Interrupt Enable (ICIE)で割り込み
while(TIMSK1 & _BV(ICIE1)) {
if(buf_flg) { // データ読み込み指令のフラグが立ったら読み込む
read_size[buf_page ^ 1] = dataFile.read( (uint8_t*)buf[buf_page ^ 1], BUF_SIZE );
buf_flg = 0; // 読み込んだらフラグを下ろす
}
}
OCR1AL = 0;
dataFile.close();
delay(5000);
}
ISR(TIMER1_CAPT_vect) { // タイマ/カウンタ1 捕獲割り込み
OCR1AL = buf[buf_page][buf_index++]; // データをPWMとして出力
if(buf_index == read_size[buf_page]) { // 現在のバッファの最後まで来たら...
if(buf_index != BUF_SIZE) TIMSK1 &= ~_BV(ICIE1); // ファイルの最後なら,ICIE1をクリア
buf_index = 0; buf_page ^= 1; buf_flg = 1; // バッファを切り替え
}
}
せっかくなので、ダ・ヴィンチ32U を使ってみました。
写真の圧電サウンダでは音量が足りませんでしたが、100円ショップスピーカを直結(たぶん良くない)したところそこそこの音量が得られました。