AVRマイコンで電子オルゴール(「私だけの電子オルゴール」というサイトのもの)を作っています。この「サクラ」というソフトで曲を作り、マイコンに書き込んだあと、スピーカーから3和音で楽器音が出るようにしたいのですが、どのようにするべきかわかりません。教えて頂けないでしょうか。
c言語で記述したプログラムを下にはりつけました。
// avr-gcc -O -mmcu=attiny45 45_3.c -o mymelo.elf
// avr-objcopy -O ihex mymelo.elf mymelo.hex
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include \"mymelo.h\"
#define V1 0xffff
#define V2 0x7fff
#define V3 0x7fff
uint16_t mi1,mi2,mi3, v1,v2,v3, vm1,vm2, cntr;
uint8_t c, c1,c2,c3, C1,C2,C3, len1,len2,len3, t, t1,t2,t3, n, icntr;
SIGNAL(SIG_OVERFLOW1){ // .125*256=32us(@8MHz)
if(n>0){
if(--cntr==0){
cntr=CNT; // 32us*(1953*120/TEMPO)=62.5ms
if(--len1==0){ // Part1の次の音符
t=t1=pgm_read_byte(mi1++);
if(t==0){
n--; // 演奏回数
mi1=(uint16_t)part1; mi2=(uint16_t)part2; mi3=(uint16_t)part3;
len1=31; len2=32; len3=32; // ポーズ(62.5ms*32=2s)
c=t1=t2=t3=0;
}else{
len1=len[t1>>5]; // L32:17.408*10=174.08ms
c1=0;C1=(C[t1&=0x1f]+64)>>7;
v1=V1;
}
}
if(--len2==0){ // Part2の次の音符
t2=pgm_read_byte(mi2++);
len2=len[t2>>5]; // L32:17.408*10=174.08ms
c2=0;C2=(C[t2&=0x1f]+64)>>7;
v2=V2;
}
if(--len3==0){ // Part3の次の音符
t3=pgm_read_byte(mi3++);
len3=len[t3>>5]; // L32:17.708*10=174.08ms
c3=0;C3=(C[t3&=0x1f]+64)>>7;
v3=V3;
}
}
vm2=vm1=0;
c++;
if(t1>1){
if(++c1==C1) c1=0; // Part1の周期は32us*C1
if(c1<(C1>>1)) vm1+=v1; // Part1の振幅を加算
else if(!(c&0x0f)) v1-=(v1>>8); // Part1の振幅減衰
}
if(t2>1){
if(++c2==C2) c2=0; // Part2の周期は32us*C2
if(c2<(C2>>1)) vm2+=v2; // Part2の振幅を加算
else if(!(c&0x0f)) v2-=(v2>>8); // Part2の振幅減衰
}
if(t3>1){
if(++c3==C3) c3=0; // Part3の周期は32us*C3
if(c3<(C3>>1)) vm2+=v3; // Part3の振幅を加算
else if(!(c&0x0f)) v3-=(v3>>8); // Part3の振幅減衰
}
OCR1A=(vm1+128)>>8; OCR1B=~((vm2+128)>>8);
}
if(icntr>0) icntr--;
}
SIGNAL(SIG_INTERRUPT0){ // External Interrupt Request 0
if(icntr==0){
if(n>0) n=0; // 演奏中ならば停止
else{
n=1; // 1回演奏
cntr=CNT; // 32us*(1953*120/TEMPO)=62.5ms
c=t1=t2=t3=0;
mi1=(uint16_t)part1; mi2=(uint16_t)part2; mi3=(uint16_t)part3;
len1=len2=len3=8; // 初期ディレイ(62.5ms*8=.5s)
}
}
icntr=255; // チャタリング防止(32*255=8.1ms)
}
int main (void){
PORTB=0x04; DDRB=0x1b; // xxxooroo, CK/1
TCCR1=0x51; // if(TCNT1==1) OC1A=1;
// else if(TCNT1==OCR1A)OC1A=0;
GTCCR=0x50; // if(TCNT1==1) OC1B=1;
// else if(TCNT1==OCR1B)OC1B=0;
OCR1C=255;
n=2; // 初めに2回演奏
cntr=CNT; // 32us*(1953*120/TEMPO)=62.5ms
c=t1=t2=t3=0;
mi1=(uint16_t)part1; mi2=(uint16_t)part2; mi3=(uint16_t)part3; // 楽譜先頭
len1=len2=len3=8; // 初期ディレイ(62.5ms*8=.5s)
TIMSK=_BV(TOIE1); GIMSK=_BV(INT0); sei(); // enable Ext SW
LOOP: // 最適化オプションでfor(;;){}はNG
if(n==0 && icntr==0){
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode(); // SE=1, sleep, SE=0
}
goto LOOP;
}