前回上手くいかなくて断念したが、原因が分かったので、まとめてみる。
上手くいったスケッチは、ここにあげておく。
動作した風景はこんな感じ。(著作権に配慮し波形だけです。)
上手くいかなかった原因は、ひとえにArduinoが遅いと言うことに尽きる。
入門用マイコンで遅い早いというのはナンセンスなのだが、
Arduinoでは、本来色々考慮しなくてはいけないところを上手く遮蔽して、
私のような初めてマイコンを触る人でも、何となくコードを書いて動くようにしてある。
本来、マイコンはブートローダを書き込むだの開始アドレスがぁとかLチカする前のお膳立てで挫折する人が多いと思う。自分もそうだし。
(ちなみにArduino UNOのマイコンであるAVRはわりと早い部類に入るので、マイコン自体が遅い訳ではない)
PCのソフトの感覚だと、最終的にコンパイルされるので、速度差は顕著に出ないと思ったが、
マイコンの世界ではPCの感覚は通用しない。1命令1クロック。(AVRの場合。http://ja.wikipedia.org/wiki/Atmel_AVR)少ないクロック数(=命令数)で如何に動かすかの世界なのだ。オマケにメモリも少ない。
例えば、デジタルポートをHIGHにするには、Arduinoでは
digitalWrite(BSYNC,HIGH);のようにするが、AVRのGCCに実はdigitalwriteなどという命令は無い。
実際のコードは以下のようになっている。(arduino-1.0.1\hardware\arduino\cores\arduino\wiring_digital.cより)
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
uint8_t oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
SREG = oldSREG;
}
 では、本来はどうなのかというと、*out_bsync |= bit_bsync;で済んでしまう。 (ピン定義とかは省略)
しかし、Arduinoのすばらしいのは、スケッチにAVR-GCCのコードが書ける(混在できる)という点。
つまり、Arduinoで一通りのことをやったら、次のステップとして、
スケッチの一部をAVR-GCCの関数に置き換えるとか出来るのである。
前回上手くいかなかったのは、
- 配列にmp3データを展開していたので、そもそもメモリが不足していた(可能性がある)
 - shiftout命令が遅すぎて、転送が間に合っていなかった。
 
この2点のようだ。
いやぁ、マイコンは奥が深い。昔々メモリが少なかったDOSの時代とは違う面白さがある。
ディスプレイなど当然無いので、再起プログラム書いてもOut of Memoryなんて出ずに暴走するし。
ステップ実行なんてシミュレータでもないと無理だし。